]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - libs/math/expression.h
initial
[xonotic/netradiant.git] / libs / math / expression.h
1 /*
2 Copyright (C) 2001-2006, William Joseph.
3 All Rights Reserved.
4
5 This file is part of GtkRadiant.
6
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20 */
21
22 #if !defined (INCLUDED_EXPRESSION_H)
23 #define INCLUDED_EXPRESSION_H
24
25 #include <math/matrix.h>
26
27 template<typename Value>
28 class Literal
29 {
30   Value m_value;
31 public:
32   typedef Value value_type;
33
34   Literal(const Value& value)
35     : m_value(value)
36   {
37   }
38   const value_type& eval() const
39   {
40     return m_value;
41   }
42 };
43
44 template<typename Value>
45 inline Literal<Value> float_literal(const Value& value)
46 {
47   return Literal<Value>(value);
48 }
49
50 template<typename Expression>
51 inline float float_for_expression(const Expression& expression)
52 {
53   return expression.eval();
54 }
55
56
57 template<typename First, typename Second>
58 class ScalarDivided
59 {
60   First first;
61   Second second;
62 public:
63   typedef typename First::value_type value_type;
64
65   ScalarDivided(const First& first_, const Second& second_) : first(first_), second(second_)
66   {
67   }
68   value_type eval() const
69   {
70     return static_cast<value_type>(first.eval() / second.eval());
71   }
72 };
73
74 template<typename First, typename Second>
75 inline ScalarDivided<First, Second> float_divided(const First& first, const Second& second)
76 {
77   return ScalarDivided<First, Second>(first, second);
78 }
79
80 template<typename First>
81 inline ScalarDivided<Literal<typename First::value_type>, First> float_reciprocal(const First& first)
82 {
83   typedef typename First::value_type first_value_type;
84   return ScalarDivided<Literal<first_value_type>, First>(float_literal(first_value_type(1.0)), first);
85 }
86
87 template<typename First>
88 class SquareRoot
89 {
90   First first;
91 public:
92   typedef typename First::value_type value_type;
93
94   SquareRoot(const First& first_) : first(first_)
95   {
96   }
97   value_type eval() const
98   {
99     return static_cast<value_type>(sqrt(first.eval()));
100   }
101 };
102
103 template<typename First>
104 inline SquareRoot<First> float_square_root(const First& first)
105 {
106   return SquareRoot<First>(first);
107 }
108
109
110 template<typename Element>
111 class BasicVector3Literal
112 {
113   const BasicVector3<Element> m_value;
114 public:
115   typedef Element value_type;
116   typedef IntegralConstant<3> dimension;
117
118   BasicVector3Literal(const BasicVector3<Element>& value)
119     : m_value(value)
120   {
121   }
122   const value_type& eval(unsigned int i) const
123   {
124     return m_value[i];
125   }
126 };
127
128 template<typename Element>
129 inline BasicVector3Literal<Element> vector3_literal(const BasicVector3<Element>& value)
130 {
131   return BasicVector3Literal<Element>(value);
132 }
133
134 typedef BasicVector3Literal<float> Vector3Literal;
135
136 template<typename Element>
137 class BasicVector3Identity
138 {
139   const BasicVector3<Element>& m_value;
140 public:
141   typedef Element value_type;
142   typedef IntegralConstant<3> dimension;
143
144   BasicVector3Identity(const BasicVector3<Element>& value)
145     : m_value(value)
146   {
147   }
148   const value_type& eval(unsigned int i) const
149   {
150     return m_value[i];
151   }
152 };
153
154 template<typename Element>
155 inline BasicVector3Identity<Element> vector3_identity(const BasicVector3<Element>& value)
156 {
157   return BasicVector3Identity<Element>(value);
158 }
159
160 typedef BasicVector3Identity<float> Vector3Identity;
161
162 template<typename Expression>
163 inline BasicVector3<typename Expression::value_type> vector3_for_expression(const Expression& expression)
164 {
165   return Vector3(expression.eval(0), expression.eval(1), expression.eval(2));
166 }
167
168
169 template<typename Operation, typename First, typename Second>
170 class VectorScalar
171 {
172   First first;
173   Literal<typename Second::value_type> second;
174 public:
175   typedef typename First::value_type value_type;
176   typedef typename First::dimension dimension;
177
178   VectorScalar(const First& first_, const Second& second_)
179     : first(first_), second(second_.eval())
180   {
181   }
182   value_type eval(unsigned int i) const
183   {
184     return Operation::apply( first.eval(i), second.eval() );
185   }
186 };
187
188
189
190 template<typename Operation, typename First, typename Second>
191 class VectorVector
192 {
193   First first;
194   Second second;
195 public:
196   typedef typename First::value_type value_type;
197   typedef typename First::dimension dimension;
198
199   VectorVector(const First& first_, const Second& second_)
200     : first(first_), second(second_)
201   {
202   }
203   value_type eval(unsigned int i) const
204   {
205     return Operation::apply(first.eval(i), second.eval(i));
206   }
207 };
208
209 template<typename First, typename Second>
210 class Added
211 {
212 public:
213   typedef First value_type;
214
215   static value_type apply(const First& first, const Second& second)
216   {
217     return static_cast<value_type>(first + second);
218   }
219 };
220
221 template<typename First, typename Second>
222 inline VectorVector<Added<typename First::value_type, typename Second::value_type>, First, Second>
223 vector_added(const First& first, const Second& second)
224 {
225   typedef typename First::value_type first_value_type;
226   typedef typename Second::value_type second_value_type;
227   return VectorVector<Added<first_value_type, second_value_type>, First, Second>(first, second);
228 }
229
230 template<typename First, typename Second>
231 class Multiplied
232 {
233 public:
234   typedef First value_type;
235
236   static value_type apply(const First& first, const Second& second)
237   {
238     return static_cast<value_type>(first * second);
239   }
240 };
241
242 template<typename First, typename Second>
243 inline VectorVector<Multiplied<typename First::value_type, typename Second::value_type>, First, Second>
244 vector_multiplied(const First& first, const Second& second)
245 {
246   typedef typename First::value_type first_value_type;
247   typedef typename Second::value_type second_value_type;
248   return VectorVector<Multiplied<first_value_type, second_value_type>, First, Second>(first, second);
249 }
250
251 template<typename First, typename Second>
252 inline VectorScalar<Multiplied<typename First::value_type, typename Second::value_type>, First, Second>
253 vector_scaled(const First& first, const Second& second)
254 {
255   typedef typename First::value_type first_value_type;
256   typedef typename Second::value_type second_value_type;
257   return VectorScalar<Multiplied<first_value_type, second_value_type>, First, Second>(first, second);
258 }
259
260 template<typename First>
261 class Negated
262 {
263 public:
264   typedef First value_type;
265
266   static value_type apply(const First& first)
267   {
268     return -first;
269   }
270 };
271
272 template<typename First, typename Operation>
273 class VectorUnary
274 {
275   First first;
276 public:
277   typedef typename First::value_type value_type;
278   typedef typename First::dimension dimension;
279
280   VectorUnary(const First& first_) : first(first_)
281   {
282   }
283   value_type eval(unsigned int i) const
284   {
285     return Operation::apply(first.eval(i));
286   }
287 };
288
289 template<typename First>
290 inline VectorUnary<First, Negated<typename First::value_type> >
291 vector_negated(const First& first)
292 {
293   typedef typename First::value_type first_value_type;
294   return VectorUnary<First, Negated<first_value_type> >(first);
295 }
296
297 template<typename First, typename Second>
298 class VectorCross
299 {
300   First first;
301   Second second;
302 public:
303   typedef typename First::value_type value_type;
304   typedef typename First::dimension dimension;
305
306   VectorCross(const First& first_, const Second& second_)
307     : first(first_), second(second_)
308   {
309   }
310   value_type eval(unsigned int i) const
311   {
312     return first.eval((i+1)%3) * second.eval((i+2)%3) - first.eval((i+2)%3) * second.eval((i+1)%3);
313   }
314 };
315
316 template<typename First, typename Second>
317 inline VectorCross<First, Second>
318 vector_cross(const First& first, const Second& second)
319 {
320   return VectorCross<First, Second>(first, second);
321 }
322
323
324 template<typename First, typename Second>
325 class VectorDot
326 {
327   First first;
328   Second second;
329 public:
330   typedef typename First::value_type value_type;
331   typedef typename First::dimension dimension;
332
333   VectorDot(const First& first_, const Second& second_)
334     : first(first_), second(second_)
335   {
336   }
337
338   template<typename Index>
339   struct eval_dot
340   {
341     static value_type apply(const First& first, const Second& second)
342     {
343       return static_cast<value_type>(
344         first.eval(Index::VALUE) * second.eval(Index::VALUE)
345         + eval_dot< IntegralConstant<Index::VALUE-1> >::apply(first, second)
346       );
347     }
348   };
349
350   template<>
351   struct eval_dot< IntegralConstant<0> >
352   {
353     static value_type apply(const First& first, const Second& second)
354     {
355       return first.eval(0) * second.eval(0);
356     }
357   };
358
359   value_type eval() const
360   {
361     return eval_dot< IntegralConstant<dimension::VALUE - 1> >::apply(first, second);
362   }
363 };
364
365
366 template<typename First, typename Second>
367 inline VectorDot<First, Second> vector_dot(const First& first, const Second& second)
368 {
369   return VectorDot<First, Second>(first, second);
370 }
371
372 template<typename First>
373 class VectorLengthSquared
374 {
375   First first;
376 public:
377   typedef typename First::value_type value_type;
378   typedef typename First::dimension dimension;
379
380   VectorLengthSquared(const First& first_)
381     : first(first_)
382   {
383   }
384
385   static value_type squared(const value_type& value)
386   {
387     return value * value;
388   }
389
390   template<typename Index>
391   struct eval_squared
392   {
393     static value_type apply(const First& first)
394     {
395       return static_cast<value_type>(
396         squared(first.eval(Index::VALUE))
397         + eval_squared< IntegralConstant<Index::VALUE - 1> >::apply(first)
398       );
399     }
400   };
401
402   template<>
403   struct eval_squared< IntegralConstant<0> >
404   {
405     static value_type apply(const First& first)
406     {
407       return squared(first.eval(0));
408     }
409   };
410
411   value_type eval() const
412   {
413     return eval_squared< IntegralConstant<dimension::VALUE - 1> >::apply(first);
414   }
415 };
416
417 template<typename First>
418 inline VectorLengthSquared<First> vector_length_squared(const First& first)
419 {
420   return VectorLengthSquared<First>(first);
421 }
422
423 template<typename First>
424 inline SquareRoot< VectorLengthSquared<First> > vector_length(const First& first)
425 {
426   return float_square_root(vector_length_squared(first));
427 }
428
429 #if 1
430 template<typename First>
431 inline VectorScalar<
432   Multiplied<typename First::value_type, typename First::value_type>,
433   First,
434   // multiple evaulations of subexpression
435   ScalarDivided<
436     Literal<typename First::value_type>,
437     SquareRoot<
438       VectorLengthSquared<First>
439     >
440   >
441 > vector_normalised(const First& first)
442 {
443   typedef typename First::value_type first_value_type;
444   return vector_scaled(first, float_reciprocal(vector_length(first)));
445 }
446 #else
447 template<typename First>
448 inline VectorScalar<
449   Multiplied<typename First::value_type, typename First::value_type>,
450   First,
451   // single evaluation of subexpression
452   Literal<typename First::value_type>
453 >
454 vector_normalised(const First& first)
455 {
456   typedef typename First::value_type first_value_type;
457   return vector_scaled(first, float_literal(static_cast<first_value_type>(first_value_type(1.0) / vector_length(first).eval())));
458 }
459 #endif
460
461
462 class Matrix4Literal
463 {
464   const Matrix4 m_value;
465 public:
466   typedef float value_type;
467   typedef IntegralConstant<4> dimension0;
468   typedef IntegralConstant<4> dimension1;
469
470   Matrix4Literal(const Matrix4& value)
471     : m_value(value)
472   {
473   }
474   const value_type& eval(unsigned int r, unsigned int c) const
475   {
476     return m_value[r*4+c];
477   }
478 };
479
480 inline Matrix4Literal matrix4_literal(const Matrix4& value)
481 {
482   return Matrix4Literal(value);
483 }
484
485 class Matrix4Identity
486 {
487   const Matrix4& m_value;
488 public:
489   typedef float value_type;
490   typedef IntegralConstant<4> dimension0;
491   typedef IntegralConstant<4> dimension1;
492
493   Matrix4Identity(const Matrix4& value)
494     : m_value(value)
495   {
496   }
497   const value_type& eval(unsigned int r, unsigned int c) const
498   {
499     return m_value[r*4+c];
500   }
501 };
502
503 inline Matrix4Identity matrix4_identity(const Matrix4& value)
504 {
505   return Matrix4Identity(value);
506 }
507
508 template<typename Expression>
509 inline Matrix4 matrix4_for_expression(const Expression& expression)
510 {
511   return Matrix4(
512     expression.eval(0, 0), expression.eval(0, 1), expression.eval(0, 2), expression.eval(0, 3),
513     expression.eval(1, 0), expression.eval(1, 1), expression.eval(1, 2), expression.eval(1, 3),
514     expression.eval(2, 0), expression.eval(2, 1), expression.eval(2, 2), expression.eval(2, 3),
515     expression.eval(3, 0), expression.eval(3, 1), expression.eval(3, 2), expression.eval(3, 3)
516   );
517 }
518
519 template<typename Expression>
520 inline Matrix4 matrix4_affine_for_expression(const Expression& expression)
521 {
522   return Matrix4(
523     expression.eval(0, 0), expression.eval(0, 1), expression.eval(0, 2), 0,
524     expression.eval(1, 0), expression.eval(1, 1), expression.eval(1, 2), 0,
525     expression.eval(2, 0), expression.eval(2, 1), expression.eval(2, 2), 0,
526     expression.eval(3, 0), expression.eval(3, 1), expression.eval(3, 2), 1
527   );
528 }
529
530
531 template<typename First, typename Second>
532 class PointMultiplied
533 {
534   const First& first;
535   const Second& second;
536 public:
537   typedef typename First::value_type value_type;
538   typedef typename First::dimension dimension;
539
540   PointMultiplied(const First& first_, const Second& second_)
541     : first(first_), second(second_)
542   {
543   }
544   value_type eval(unsigned int i) const
545   {
546     return static_cast<value_type>(second.eval(0, i) * first.eval(0)
547       + second.eval(1, i) * first.eval(1)
548       + second.eval(2, i) * first.eval(2)
549       + second.eval(3, i));
550   }
551 };
552
553 template<typename First, typename Second>
554 inline PointMultiplied<First, Second> point_multiplied(const First& point, const Second& matrix)
555 {
556   return PointMultiplied<First, Second>(point, matrix);
557 }
558
559 template<typename First, typename Second>
560 class Matrix4Multiplied
561 {
562   const First& first;
563   const Second& second;
564 public:
565   typedef typename First::value_type value_type;
566   typedef typename First::dimension0 dimension0;
567   typedef typename First::dimension1 dimension1;
568
569   Matrix4Multiplied(const First& first_, const Second& second_)
570     : first(first_), second(second_)
571   {
572   }
573
574   value_type eval(unsigned int r, unsigned int c) const
575   {
576     return static_cast<value_type>(
577       second.eval(r, 0) * first.eval(0, c)
578       + second.eval(r, 1) * first.eval(1, c)
579       + second.eval(r, 2) * first.eval(2, c)
580       + second.eval(r, 3) * first.eval(3, c)
581     );
582   }
583 };
584
585 template<typename First, typename Second>
586 inline Matrix4Multiplied<First, Second> matrix4_multiplied(const First& first, const Second& second)
587 {
588   return Matrix4Multiplied<First, Second>(first, second);
589 }
590
591 template<typename First>
592 class MatrixTransposed
593 {
594   const First& first;
595 public:
596   typedef typename First::value_type value_type;
597   typedef typename First::dimension0 dimension0;
598   typedef typename First::dimension1 dimension1;
599
600   MatrixTransposed(const First& first_)
601     : first(first_)
602   {
603   }
604
605   value_type eval(unsigned int r, unsigned int c) const
606   {
607     return first.eval(c, r);
608   }
609 };
610
611 template<typename First>
612 inline MatrixTransposed<First> matrix_transposed(const First& first)
613 {
614   return MatrixTransposed<First>(first);
615 }
616
617 #endif