v1.1.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Groups Pages
math.h
1 /* -*- mode: C; c-basic-offset: 4; intent-tabs-mode: nil -*-
2  *
3  * This file is part of the public interface to the Sifteo SDK.
4  * Copyright <c> 2012 Sifteo, Inc. All rights reserved.
5  */
6 
7 #pragma once
8 #ifdef NOT_USERSPACE
9 # error This is a userspace-only header, not allowed by the current build.
10 #endif
11 
12 #include <sifteo/abi.h>
13 #include <sifteo/macros.h>
14 
15 namespace Sifteo {
16 
25 /*
26  * Common mathematical constants
27  */
28 
29 #define M_E 2.71828182845904523536028747135266250
30 #define M_LOG2E 1.44269504088896340735992468100189214
31 #define M_LOG10E 0.434294481903251827651128918916605082
32 #define M_LN2 0.693147180559945309417232121458176568
33 #define M_LN10 2.30258509299404568401799145468436421
34 #define M_PI 3.14159265358979323846264338327950288
35 #define M_TAU 6.2831853071795862
36 #define M_PI_2 1.57079632679489661923132169163975144
37 #define M_PI_4 0.785398163397448309615660845819875721
38 #define M_1_PI 0.318309886183790671537767526745028724
39 #define M_2_PI 0.636619772367581343075535053490057448
40 #define M_2_SQRTPI 1.12837916709551257389615890312154517
41 #define M_SQRT2 1.41421356237309504880168872420969808
42 #define M_SQRT1_2 0.707106781186547524400844362104849039
43 #define MAXFLOAT ((float)3.40282346638528860e+38)
44 #define NAN __builtin_nanf("0x7fc00000")
45 
46 
53 template <typename T> inline T clamp(const T& value, const T& low, const T& high)
54 {
55  if (value < low) {
56  return low;
57  }
58  if (value > high) {
59  return high;
60  }
61  return value;
62 }
63 
71 template <typename T> inline T abs(const T& value)
72 {
73  if (value < 0) {
74  return -value;
75  }
76  return value;
77 }
78 
87 template <typename T> inline T lslc(const T& value, int bits)
88 {
89  if (bits < 0)
90  return value;
91  if (bits >= sizeof(T) * 8)
92  return 0;
93  return value << (unsigned)bits;
94 }
95 
103 template <typename T> inline T lsrc(const T& value, int bits)
104 {
105  if (bits < 0)
106  return value;
107  if (bits >= sizeof(T) * 8)
108  return 0;
109  return value >> (unsigned)bits;
110 }
111 
120 template <typename T> inline T bitRange(int begin, int end)
121 {
122  return lslc((T)-1, begin) & ~lslc((T)-1, end);
123 }
124 
135 inline unsigned clz(uint32_t word)
136 {
137  return __builtin_clz(word);
138 }
139 
150 inline unsigned ffs(uint32_t word)
151 {
152  // Reference: http://en.wikipedia.org/wiki/Find_first_set#Properties_and_relations
153  return 32 - __builtin_clz(word & -word);
154 }
155 
157 float inline fmod(float a, float b)
158 {
159  uint32_t r = _SYS_fmodf(reinterpret_cast<uint32_t&>(a), reinterpret_cast<uint32_t&>(b));
160  return reinterpret_cast<float&>(r);
161 }
162 
164 double inline fmod(double a, double b)
165 {
166  uint64_t ia = reinterpret_cast<uint64_t&>(a);
167  uint64_t ib = reinterpret_cast<uint64_t&>(b);
168  uint64_t r = _SYS_fmod(ia, ia >> 32, ib, ib >> 32);
169  return reinterpret_cast<double&>(r);
170 }
171 
173 float inline pow(float a, float b)
174 {
175  uint32_t r = _SYS_powf(reinterpret_cast<uint32_t&>(a), reinterpret_cast<uint32_t&>(b));
176  return reinterpret_cast<float&>(r);
177 }
178 
180 double inline pow(double a, double b)
181 {
182  uint64_t ia = reinterpret_cast<uint64_t&>(a);
183  uint64_t ib = reinterpret_cast<uint64_t&>(b);
184  uint64_t r = _SYS_pow(ia, ia >> 32, ib, ib >> 32);
185  return reinterpret_cast<double&>(r);
186 }
187 
189 unsigned inline umod(int a, int b)
190 {
191  int r = a % b;
192  if (r < 0)
193  r += b;
194  return r;
195 }
196 
198 template <typename T> inline T ceildiv(T numerator, T denominator) {
199  return (numerator + (denominator - 1)) / denominator;
200 }
201 
206 template <typename T> inline T roundup(T numerator, T denominator) {
207  return ceildiv(numerator, denominator) * denominator;
208 }
209 
211 float inline log(float a)
212 {
213  uint32_t r = _SYS_logf(reinterpret_cast<uint32_t&>(a));
214  return reinterpret_cast<float&>(r);
215 }
216 
218 double inline log(double a)
219 {
220  uint64_t ia = reinterpret_cast<uint64_t&>(a);
221  uint64_t r = _SYS_logd(ia, ia >> 32);
222  return reinterpret_cast<double&>(r);
223 }
224 
226 float inline sqrt(float a)
227 {
228  uint32_t r = _SYS_sqrtf(reinterpret_cast<uint32_t&>(a));
229  return reinterpret_cast<float&>(r);
230 }
231 
233 double inline sqrt(double a)
234 {
235  uint64_t ia = reinterpret_cast<uint64_t&>(a);
236  uint64_t r = _SYS_sqrt(ia, ia >> 32);
237  return reinterpret_cast<double&>(r);
238 }
239 
246 float inline sin(float x)
247 {
248  uint32_t r = _SYS_sinf(reinterpret_cast<uint32_t&>(x));
249  return reinterpret_cast<float&>(r);
250 }
251 
258 float inline cos(float x)
259 {
260  uint32_t r = _SYS_cosf(reinterpret_cast<uint32_t&>(x));
261  return reinterpret_cast<float&>(r);
262 }
263 
265 float inline tan(float x)
266 {
267  uint32_t r = _SYS_tanf(reinterpret_cast<uint32_t&>(x));
268  return reinterpret_cast<float&>(r);
269 }
270 
272 float inline atan(float x)
273 {
274  uint32_t r = _SYS_atanf(reinterpret_cast<uint32_t&>(x));
275  return reinterpret_cast<float&>(r);
276 }
277 
284 float inline atan2(float a, float b)
285 {
286  uint32_t r = _SYS_atan2f(reinterpret_cast<uint32_t&>(a), reinterpret_cast<uint32_t&>(b));
287  return reinterpret_cast<float&>(r);
288 }
289 
297 void inline sincos(float x, float *s, float *c)
298 {
299  _SYS_sincosf(reinterpret_cast<uint32_t&>(x), s, c);
300 }
301 
309 float inline tsin(float x)
310 {
311  uint32_t r = _SYS_tsinf(reinterpret_cast<uint32_t&>(x));
312  return reinterpret_cast<float&>(r);
313 }
314 
322 float inline tcos(float x)
323 {
324  uint32_t r = _SYS_tcosf(reinterpret_cast<uint32_t&>(x));
325  return reinterpret_cast<float&>(r);
326 }
327 
342 int inline tsini(int x)
343 {
344  return _SYS_tsini(x);
345 }
346 
362 int inline tcosi(int x)
363 {
364  return _SYS_tcosi(x);
365 }
366 
376 bool inline isunordered(float a, float b = 0.f)
377 {
378  return __builtin_isunordered(a, b);
379 }
380 
390 bool inline isunordered(double a, double b = 0.f)
391 {
392  return __builtin_isunordered(a, b);
393 }
394 
407 template <typename T> inline long ceil(const T value)
408 {
409  long result = value;
410  if (result >= 0 && result < value) {
411  return result+1;
412  }
413  return result;
414 }
415 
428 template <typename T> inline long floor(const T value)
429 {
430  long result = value;
431  if (result <= 0 && result > value) {
432  return result - 1;
433  }
434  return result;
435 }
436 
450 template <typename T> inline long round(const T value)
451 {
452  return floor(value + 0.5);
453 }
454 
459 template <typename T> inline bool almostEqual(const T a, const T b, const T epsilon)
460 {
461  return abs(a-b) < epsilon;
462 }
463 
464 
469 template <typename T> struct Vector2 {
470  T x;
471  T y;
472 
476  void set(T _x, T _y) {
477  x = _x;
478  y = _y;
479  }
480 
484  void setPolar(float angle, float magnitude) {
485  float s, c;
486  sincos(angle, &s, &c);
487  x = c * magnitude;
488  y = s * magnitude;
489  }
490 
494  Vector2<T> rotate(float angle) const {
495  float s, c;
496  sincos(angle, &s, &c);
497  Vector2<T> result = { x*c - y*s, x*s + y*c };
498  return result;
499  }
500 
509  Vector2<T> rotateI(int angle) const {
510  Vector2<T> a1 = { -y, x };
511  Vector2<T> a2 = { -x, -y };
512  Vector2<T> a3 = { y, -x };
513  switch (angle) {
514  default: ASSERT(0);
515  case 0: return *this;
516  case 1: return a1;
517  case 2: return a2;
518  case 3: return a3;
519  }
520  }
521 
530  static Vector2<T> unit(int side) {
531  Vector2<T> a0 = { 0, -1 };
532  Vector2<T> a1 = { -1, 0 };
533  Vector2<T> a2 = { 0, 1 };
534  Vector2<T> a3 = { 1, 0 };
535  switch(side) {
536  default: ASSERT(0);
537  case 0: return a0;
538  case 1: return a1;
539  case 2: return a2;
540  case 3: return a3;
541  }
542  }
543 
549  T len2() const {
550  return ( x * x + y * y );
551  }
552 
556  T len() const {
557  return sqrt(len2());
558  }
559 
563  T lenManhattan() const {
564  return abs(x) + abs(y);
565  }
566 
573  return *this / len();
574  }
575 
579  Vector2<int> round() const {
580  Vector2<int> result = { x + 0.5f, y + 0.5f };
581  return result;
582  }
583 
588  template <typename R> Vector2<R> cast() const {
589  Vector2<R> result = { x, y };
590  return result;
591  }
592 
600  Vector2<T> result = { x*u.x - y*u.y, x*u.y + y*u.x };
601  return result;
602  }
603 
605  Vector2<int> toInt() const { return cast<int>(); }
607  Vector2<float> toFloat() const { return cast<float>(); }
609  Vector2<double> toDouble() const { return cast<double>(); }
610 
611  // Implicit casts
612  operator Vector2<int> () const { return cast<int>(); }
613  operator Vector2<unsigned> () const { return cast<unsigned>(); }
614  operator Vector2<short> () const { return cast<short>(); }
615  operator Vector2<unsigned short> () const { return cast<unsigned short>(); }
616  operator Vector2<int8_t> () const { return cast<int8_t>(); }
617  operator Vector2<uint8_t> () const { return cast<uint8_t>(); }
618  operator Vector2<float> () const { return cast<float>(); }
619  operator Vector2<double> () const { return cast<double>(); }
620 };
621 
630 
639 template <typename T> inline Vector2<T> vec(T x, T y) {
640  Vector2<T> result = { x, y };
641  return result;
642 }
643 
645 template <typename T> inline T dot(Vector2<T> u, Vector2<T> v) {
646  return u.x * v.x + u.y * v.y;
647 }
648 
650 template <typename T> inline Vector2<T> polar(T angle, T magnitude) {
651  Vector2<T> result;
652  result.setPolar(angle, magnitude);
653  return result;
654 }
655 
656 // Vector operations
657 template <typename T> inline Vector2<T> operator-(Vector2<T> u) { return vec<T>(-u.x, -u.y); }
658 template <typename T> inline Vector2<T> operator+=(Vector2<T> &u, Vector2<T> v) { return vec<T>(u.x+=v.x, u.y+=v.y); }
659 template <typename T> inline Vector2<T> operator-=(Vector2<T> &u, Vector2<T> v) { return vec<T>(u.x-=v.x, u.y-=v.y); }
660 template <typename T> inline Vector2<T> operator+(Vector2<T> u, Vector2<T> v) { return vec<T>(u.x+v.x, u.y+v.y); }
661 template <typename T> inline Vector2<T> operator-(Vector2<T> u, Vector2<T> v) { return vec<T>(u.x-v.x, u.y-v.y); }
662 template <typename T> inline Vector2<T> operator*(Vector2<T> u, Vector2<T> v) { return vec<T>(u.x*v.x, u.y*v.y); }
663 template <typename T> inline bool operator==(Vector2<T> u, Vector2<T> v) { return u.x == v.x && u.y == v.y; }
664 template <typename T> inline bool operator!=(Vector2<T> u, Vector2<T> v) { return u.x != v.x || u.y != v.y; }
665 
666 // Scalar int promotion
667 template <typename T> inline Int2 operator*(int k, Vector2<T> v) { return vec<int>(k*v.x, k*v.y); }
668 template <typename T> inline Int2 operator*(Vector2<T> v, int k) { return vec<int>(k*v.x, k*v.y); }
669 template <typename T> inline Int2 operator/(Vector2<T> v, int k) { return vec<int>(v.x/k, v.y/k); }
670 template <typename T> inline Int2 operator+=(Vector2<T> &u, int k) { return vec<int>(u.x+=k, u.y+=k); }
671 template <typename T> inline Int2 operator*=(Vector2<T> &u, int k) { return vec<int>(u.x*=k, u.y*=k); }
672 template <typename T> inline Int2 operator<<(Vector2<T> u, int shift) { return vec<int>(u.x<<shift, u.y<<shift); }
673 template <typename T> inline Int2 operator>>(Vector2<T> u, int shift) { return vec<int>(u.x>>shift, u.y>>shift); }
674 
675 // Scalar float promotion
676 template <typename T> inline Float2 operator*(float k, Vector2<T> v) { return vec<float>(k*v.x, k*v.y); }
677 template <typename T> inline Float2 operator*(Vector2<T> v, float k) { return vec<float>(k*v.x, k*v.y); }
678 template <typename T> inline Float2 operator/(Vector2<T> v, float k) { return vec<float>(v.x/k, v.y/k); }
679 template <typename T> inline Float2 operator+=(Vector2<T> &u, float k) { return vec<float>(u.x+=k, u.y+=k); }
680 template <typename T> inline Float2 operator*=(Vector2<T> &u, float k) { return vec<float>(u.x*=k, u.y*=k); }
681 
682 // Scalar double promotion
683 template <typename T> inline Double2 operator*(double k, Vector2<T> v) { return vec<double>(k*v.x, k*v.y); }
684 template <typename T> inline Double2 operator*(Vector2<T> v, double k) { return vec<double>(k*v.x, k*v.y); }
685 template <typename T> inline Double2 operator/(Vector2<T> v, double k) { return vec<double>(v.x/k, v.y/k); }
686 template <typename T> inline Double2 operator+=(Vector2<T> &u, double k) { return vec<double>(u.x+=k, u.y+=k); }
687 template <typename T> inline Double2 operator*=(Vector2<T> &u, double k) { return vec<double>(u.x*=k, u.y*=k); }
688 
689 // Vector int -> float promotion
690 inline Vector2<float> operator+=(Vector2<float> &u, Int2 v) { return vec(u.x+=v.x, u.y+=v.y); }
691 inline Vector2<float> operator-=(Vector2<float> &u, Int2 v) { return vec(u.x-=v.x, u.y-=v.y); }
692 inline Vector2<float> operator+(Vector2<float> u, Int2 v) { return vec(u.x+v.x, u.y+v.y); }
693 inline Vector2<float> operator-(Vector2<float> u, Int2 v) { return vec(u.x-v.x, u.y-v.y); }
694 inline Vector2<float> operator*(Vector2<float> u, Int2 v) { return vec(u.x*v.x, u.y*v.y); }
695 inline Vector2<float> operator+(Int2 u, Vector2<float> v) { return vec(u.x+v.x, u.y+v.y); }
696 inline Vector2<float> operator-(Int2 u, Vector2<float> v) { return vec(u.x-v.x, u.y-v.y); }
697 inline Vector2<float> operator*(Int2 u, Vector2<float> v) { return vec(u.x*v.x, u.y*v.y); }
698 
699 
704 template <typename T> struct Vector3 {
705  T x;
706  T y;
707  T z;
708 
710  void set(T _x, T _y, T _z) {
711  x = _x;
712  y = _y;
713  z = _z;
714  }
715 
716  Vector2<T> xy() const { return vec(x, y); }
717  Vector2<T> xz() const { return vec(x, z); }
718  Vector2<T> yx() const { return vec(y, x); }
719  Vector2<T> yz() const { return vec(y, z); }
720  Vector2<T> zx() const { return vec(z, x); }
721  Vector2<T> zy() const { return vec(z, y); }
722 
728  T len2() const {
729  return ( x * x + y * y + z * z );
730  }
731 
735  T len() const {
736  return sqrt(len2());
737  }
738 
742  T lenManhattan() const {
743  return abs(x) + abs(y) + abs(z);
744  }
745 
752  return *this / len();
753  }
754 
758  Vector3<int> round() const {
759  Vector3<int> result = { x + 0.5f, y + 0.5f, z + 0.5f };
760  return result;
761  }
762 
766  Vector3<T> zRotate(float angle) const {
767  float s, c;
768  sincos(angle, &s, &c);
769  Vector3<T> result = { x*c - y*s, x*s + y*c, z };
770  return result;
771  }
772 
781  Vector3<T> zRotateI(int angle) const {
782  Vector3<T> a1 = { -y, x, z };
783  Vector3<T> a2 = { -x, -y, z };
784  Vector3<T> a3 = { y, -x, z };
785  switch (angle) {
786  default: ASSERT(0);
787  case 0: return *this;
788  case 1: return a1;
789  case 2: return a2;
790  case 3: return a3;
791  }
792  }
793 
798  template <typename R> Vector3<R> cast() const {
799  Vector3<R> result = { x, y, z };
800  return result;
801  }
802 
804  Vector3<int> toInt() const { return cast<int>(); }
806  Vector3<float> toFloat() const { return cast<float>(); }
808  Vector3<double> toDouble() const { return cast<double>(); }
809 
810  // Implicit casts
811  operator Vector3<int> () const { return cast<int>(); }
812  operator Vector3<unsigned> () const { return cast<unsigned>(); }
813  operator Vector3<short> () const { return cast<short>(); }
814  operator Vector3<unsigned short> () const { return cast<unsigned short>(); }
815  operator Vector3<int8_t> () const { return cast<int8_t>(); }
816  operator Vector3<uint8_t> () const { return cast<uint8_t>(); }
817  operator Vector3<float> () const { return cast<float>(); }
818  operator Vector3<double> () const { return cast<double>(); }
819 };
820 
829 
838 template <typename T> inline Vector3<T> vec(T x, T y, T z) {
839  Vector3<T> result = { x, y, z };
840  return result;
841 }
842 
844 template <typename T> inline T dot(Vector3<T> u, Vector3<T> v) {
845  return u.x * v.x + u.y * v.y + u.z * v.z;
846 }
847 
849 template <typename T> inline T cross(T u, T v) {
850  return vec(u.y * v.z - u.z * v.y,
851  u.z * v.x - u.x * v.z,
852  u.x * v.y - u.y * v.x);
853 }
854 
855 // Vector operations
856 template <typename T> inline Vector3<T> operator-(Vector3<T> u) { return vec<T>(-u.x, -u.y, -u.z); }
857 template <typename T> inline Vector3<T> operator+=(Vector3<T> &u, Vector3<T> v) { return vec<T>(u.x+=v.x, u.y+=v.y, u.z+=v.z); }
858 template <typename T> inline Vector3<T> operator-=(Vector3<T> &u, Vector3<T> v) { return vec<T>(u.x-=v.x, u.y-=v.y, u.z-=v.z); }
859 template <typename T> inline Vector3<T> operator+(Vector3<T> u, Vector3<T> v) { return vec<T>(u.x+v.x, u.y+v.y, u.z+v.z); }
860 template <typename T> inline Vector3<T> operator-(Vector3<T> u, Vector3<T> v) { return vec<T>(u.x-v.x, u.y-v.y, u.z-v.z); }
861 template <typename T> inline Vector3<T> operator*(Vector3<T> u, Vector3<T> v) { return vec<T>(u.x*v.x, u.y*v.y, u.z*v.z); }
862 template <typename T> inline bool operator==(Vector3<T> u, Vector3<T> v) { return u.x == v.x && u.y == v.y && u.z == v.z; }
863 template <typename T> inline bool operator!=(Vector3<T> u, Vector3<T> v) { return u.x != v.x || u.y != v.y || u.z != v.z; }
864 
865 // Scalar int promotion
866 template <typename T> inline Int3 operator*(int k, Vector3<T> v) { return vec<int>(k*v.x, k*v.y, k*v.z); }
867 template <typename T> inline Int3 operator*(Vector3<T> v, int k) { return vec<int>(k*v.x, k*v.y, k*v.z); }
868 template <typename T> inline Int3 operator/(Vector3<T> v, int k) { return vec<int>(v.x/k, v.y/k, v.z/k); }
869 template <typename T> inline Int3 operator+=(Vector3<T> &u, int k) { return vec<int>(u.x+=k, u.y+=k, u.z+=k); }
870 template <typename T> inline Int3 operator*=(Vector3<T> &u, int k) { return vec<int>(u.x*=k, u.y*=k, u.z*=k); }
871 template <typename T> inline Int3 operator<<(Vector3<T> u, int shift) { return vec<int>(u.x<<shift, u.y<<shift, u.z<<shift); }
872 template <typename T> inline Int3 operator>>(Vector3<T> u, int shift) { return vec<int>(u.x>>shift, u.y>>shift, u.z>>shift); }
873 
874 // Scalar float promotion
875 template <typename T> inline Float3 operator*(float k, Vector3<T> v) { return vec<float>(k*v.x, k*v.y, k*v.z); }
876 template <typename T> inline Float3 operator*(Vector3<T> v, float k) { return vec<float>(k*v.x, k*v.y, k*v.z); }
877 template <typename T> inline Float3 operator/(Vector3<T> v, float k) { return vec<float>(v.x/k, v.y/k, v.z/k); }
878 template <typename T> inline Float3 operator+=(Vector3<T> &u, float k) { return vec<float>(u.x+=k, u.y+=k, u.z+=k); }
879 template <typename T> inline Float3 operator*=(Vector3<T> &u, float k) { return vec<float>(u.x*=k, u.y*=k, u.z*=k); }
880 
881 // Scalar double promotion
882 template <typename T> inline Double3 operator*(double k, Vector3<T> v) { return vec<double>(k*v.x, k*v.y, k*v.z); }
883 template <typename T> inline Double3 operator*(Vector3<T> v, double k) { return vec<double>(k*v.x, k*v.y, k*v.z); }
884 template <typename T> inline Double3 operator/(Vector3<T> v, double k) { return vec<double>(v.x/k, v.y/k, v.z/k); }
885 template <typename T> inline Double3 operator+=(Vector3<T> &u, double k) { return vec<double>(u.x+=k, u.y+=k, u.z+=k); }
886 template <typename T> inline Double3 operator*=(Vector3<T> &u, double k) { return vec<double>(u.x*=k, u.y*=k, u.z*=k); }
887 
888 // Vector int -> float promotion
889 inline Float3 operator+=(Float3 &u, Int3 v) { return vec(u.x+=v.x, u.y+=v.y, u.z+=v.z); }
890 inline Float3 operator-=(Float3 &u, Int3 v) { return vec(u.x-=v.x, u.y-=v.y, u.z-=v.z); }
891 inline Float3 operator+(Float3 u, Int3 v) { return vec(u.x+v.x, u.y+v.y, u.z+v.z); }
892 inline Float3 operator-(Float3 u, Int3 v) { return vec(u.x-v.x, u.y-v.y, u.z-v.z); }
893 inline Float3 operator*(Float3 u, Int3 v) { return vec(u.x*v.x, u.y*v.y, u.z*v.z); }
894 inline Float3 operator+(Int3 u, Float3 v) { return vec(u.x+v.x, u.y+v.y, u.z+v.z); }
895 inline Float3 operator-(Int3 u, Float3 v) { return vec(u.x-v.x, u.y-v.y, u.z-v.z); }
896 inline Float3 operator*(Int3 u, Float3 v) { return vec(u.x*v.x, u.y*v.y, u.z*v.z); }
897 
898 
908 struct Random {
909  _SYSPseudoRandomState state;
910 
912  Random() {
913  seed();
914  }
915 
917  Random(uint32_t s) {
918  seed(s);
919  }
920 
926  void seed(uint32_t s) {
927  _SYS_prng_init(&state, s);
928  }
929 
935  void seed() {
936  seed((uint32_t) _SYS_ticks_ns());
937  }
938 
940  uint32_t raw() {
941  return _SYS_prng_value(&state);
942  }
943 
945  float random() {
946  return raw() * (1.0f / 0xFFFFFFFF);
947  }
948 
950  float expovariate(float averageInterval) {
951  return -averageInterval * log(1.0f - random());
952  }
953 
962  bool chance(float probability) {
963  // Use 31 bits, to give us range to represent probability=1.
964  const uint32_t mask = 0x7FFFFFFF;
965  uint32_t threshold = probability * (mask + 1);
966  return (raw() & mask) < threshold;
967  }
968 
973  float uniform(float a, float b) {
974  // Order of operations here allows constant folding if the endpoints are constant
975  return a + raw() * ((b-a) / 0xFFFFFFFF);
976  }
977 
982  template <typename T>
983  T randint(T a, T b) {
984  return T(a + _SYS_prng_valueBounded(&state, b - a));
985  }
986 
991  template <typename T>
992  T randrange(T a, T b) {
993  return randint<T>(a, T(b - 1));
994  }
995 
1002  template <typename T>
1003  T randrange(T count) {
1004  return randrange<T>(T(0), count);
1005  }
1006 
1007 };
1008 
1009 
1024  float cx;
1025  float cy;
1026  float xx;
1027  float xy;
1028  float yx;
1029  float yy;
1030 
1033 
1035  AffineMatrix(float _xx, float _yx, float _cx,
1036  float _xy, float _yy, float _cy)
1037  : cx(_cx), cy(_cy), xx(_xx),
1038  xy(_xy), yx(_yx), yy(_yy) {}
1039 
1042  return AffineMatrix(1, 0, 0,
1043  0, 1, 0);
1044  }
1045 
1047  static AffineMatrix scaling(float s) {
1048  float inv_s = 1.0f / s;
1049  return AffineMatrix(inv_s, 0, 0,
1050  0, inv_s, 0);
1051  }
1052 
1054  static AffineMatrix translation(float x, float y) {
1055  return AffineMatrix(1, 0, x,
1056  0, 1, y);
1057  }
1058 
1061  return AffineMatrix(1, 0, v.x,
1062  0, 1, v.y);
1063  }
1064 
1066  static AffineMatrix rotation(float angle) {
1067  float s, c;
1068  sincos(angle, &s, &c);
1069  return AffineMatrix(c, -s, 0,
1070  s, c, 0);
1071  }
1072 
1074  void operator*= (const AffineMatrix &m) {
1075  AffineMatrix n;
1076 
1077  n.cx = xx*m.cx + yx*m.cy + cx;
1078  n.cy = xy*m.cx + yy*m.cy + cy;
1079  n.xx = xx*m.xx + yx*m.xy;
1080  n.xy = xy*m.xx + yy*m.xy;
1081  n.yx = xx*m.yx + yx*m.yy;
1082  n.yy = xy*m.yx + yy*m.yy;
1083 
1084  *this = n;
1085  }
1086 
1088  void translate(float x, float y) {
1089  *this *= translation(x, y);
1090  }
1091 
1093  void translate(Float2 v) {
1094  *this *= translation(v);
1095  }
1096 
1098  void rotate(float angle) {
1099  *this *= rotation(angle);
1100  }
1101 
1103  void scale(float s) {
1104  *this *= scaling(s);
1105  }
1106 };
1107 
1112 } // namespace Sifteo