Allolib  1.0
C++ Components For Interactive Multimedia
al_Functions.hpp
1 #ifndef INCLUDE_AL_MATH_FUNCTIONS_HPP
2 #define INCLUDE_AL_MATH_FUNCTIONS_HPP
3 
4 /* Allocore --
5  Multimedia / virtual environment application class library
6 
7  Copyright (C) 2009. AlloSphere Research Group, Media Arts & Technology, UCSB.
8  Copyright (C) 2012. The Regents of the University of California.
9  All rights reserved.
10 
11  Redistribution and use in source and binary forms, with or without
12  modification, are permitted provided that the following conditions are met:
13 
14  Redistributions of source code must retain the above copyright notice,
15  this list of conditions and the following disclaimer.
16 
17  Redistributions in binary form must reproduce the above copyright
18  notice, this list of conditions and the following disclaimer in the
19  documentation and/or other materials provided with the distribution.
20 
21  Neither the name of the University of California nor the names of its
22  contributors may be used to endorse or promote products derived from
23  this software without specific prior written permission.
24 
25  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
29  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35  POSSIBILITY OF SUCH DAMAGE.
36 
37 
38  File description:
39  This includes various commonly used mathematical functions that are not
40  included in the standard C/C++ math libraries.
41 
42  File author(s):
43  Lance Putnam, 2006, putnam.lance@gmail.com
44 */
45 
46 #include <algorithm>
47 #include <cmath>
48 
49 #include "al/math/al_Constants.hpp"
50 
51 namespace al {
52 
54 
63 bool aeq(float a, float b, int maxULP = 10);
64 bool aeq(double a, double b, int maxULP = 10);
65 
69 template <class T>
70 inline T ampTodB(const T& amp) {
71  return 20 * std::log(amp);
72 }
73 
77 template <class T>
78 T atLeast(const T& v, const T& eps);
79 
83 
84 // Author: Jim Shima, http://www.dspguru.com/comp.dsp/tricks/alg/fxdatan2.htm.
85 // |error| < 0.01 rad
86 template <class T>
87 T atan2Fast(const T& y, const T& x);
88 
90 
95 uint32_t bitsSet(uint32_t v);
96 
100 template <class T>
101 T ceil(const T& val, const T& step);
102 template <class T>
103 T ceil(const T& val, const T& step, const T& recStep);
104 
106 inline uint32_t ceilEven(uint32_t v) { return v += v & 1UL; }
107 
109 
115 uint32_t ceilPow2(uint32_t value);
116 
120 template <class T>
121 T clip(const T& value, const T& hi = T(1), const T& lo = T(0));
122 
124 
130 template <class T>
131 T clip(const T& v, int& clipFlag, const T& hi, const T& lo);
132 
136 template <class T>
137 T clipS(const T& value, const T& hi = T(1));
138 
142 template <class T>
143 inline T dBToAmp(const T& db) {
144  return ::pow(10, db / 20.);
145 }
146 
150 template <class T>
151 bool even(const T& v);
152 
157 template <class T>
158 T erf(const T& v);
159 
163 uint32_t factorial(uint32_t n0to12);
164 
168 double factorialSqrt(int v);
169 
173 template <class T>
174 T floor(const T& val, const T& step);
175 template <class T>
176 T floor(const T& val, const T& step, const T& recStep);
177 
179 
185 uint32_t floorPow2(uint32_t value);
186 
188 
194 template <class T>
195 T fold(const T& value, const T& hi = T(1), const T& lo = T(0));
196 
200 template <class T>
201 T foldOnce(const T& value, const T& hi = T(1), const T& lo = T(0));
202 
206 template <class T>
207 T gaussian(const T& v);
208 
212 template <class T>
213 T gcd(const T& x, const T& y);
214 
215 template <typename T, typename... Ts>
216 T gcd(const T& x, const Ts&... rest) {
217  return gcd(x, gcd(rest...));
218 }
219 
225 template <class T>
226 T gudermannian(const T& x);
227 
229 
236 template <class T>
237 T laguerreL(int n, int k, T x);
238 
240 template <class T>
241 T lcm(const T& x, const T& y);
242 
255 template <class T>
256 T legendreP(int l, int m, T t);
257 template <class T>
258 T legendreP(int l, int m, T ct, T st);
259 
263 template <class T>
264 bool lessAbs(const T& v, const T& eps = T(0.000001));
265 
269 template <typename T>
270 T max(const T& v1, const T& v2, const T& v3);
271 
275 template <class T>
276 T mean(const T& v1, const T& v2);
277 
281 template <class T>
282 T min(const T& v1, const T& v2, const T& v3);
283 
287 template <class T>
288 inline T nearestDiv(T of, T to) {
289  return to / round(to / of);
290 }
291 
296 template <class T>
297 T nextAfter(const T& x, const T& y);
298 
302 template <class T>
303 T nextMultiple(T val, T multiple);
304 
308 template <class T>
309 T numInt(const T& v);
310 
314 template <class T>
315 bool odd(const T& v);
316 
320 template <class T>
321 T poly(const T& x, const T& a0, const T& a1, const T& a2);
322 
326 template <class T>
327 T poly(const T& x, const T& a0, const T& a1, const T& a2, const T& a3);
328 
329 template <class T>
330 T pow2(const T& v);
331 template <class T>
332 T pow2S(const T& v);
333 template <class T>
334 T pow3(const T& v);
335 template <class T>
336 T pow3Abs(const T& v);
337 template <class T>
338 T pow4(const T& v);
339 template <class T>
340 T pow5(const T& v);
341 template <class T>
342 T pow6(const T& v);
343 template <class T>
344 T pow8(const T& v);
345 template <class T>
346 T pow16(const T& v);
347 template <class T>
348 T pow64(const T& v);
349 
351 
356 template <class T>
357 T powN(T base, unsigned power);
358 
362 unsigned char prime(uint32_t n);
363 
367 template <class T>
368 T round(const T& v, const T& step);
369 
374 template <class T>
375 T round(const T& v, const T& step, const T& recStep);
376 
380 template <class T>
381 T roundAway(const T& v);
382 
387 template <class T>
388 T roundAway(const T& v, const T& step);
389 
393 template <class T>
394 T sgn(const T& v, const T& norm = T(1));
395 
399 template <class T>
400 T sinc(const T& radians, const T& eps = T(0.0001));
401 
405 template <class T>
406 T slope(const T& x1, const T& y1, const T& x2, const T& y2);
407 
411 template <class T>
412 void sort(T& value1, T& value2);
413 
417 template <class T>
418 T sumOfSquares(T n);
419 
421 
427 uint32_t trailingZeroes(uint32_t v);
428 
432 template <class T>
433 T trunc(const T& v, const T& step);
434 
439 template <class T>
440 T trunc(const T& v, const T& step, const T& recStep);
441 
445 template <class T>
446 bool within(const T& v, const T& lo, const T& hi);
447 
451 template <class T>
452 bool within3(const T& v1, const T& v2, const T& v3, const T& lo, const T& hi);
453 
457 template <class T>
458 bool withinIE(const T& v, const T& lo, const T& hi);
459 
463 template <class T>
464 T wrap(const T& value, const T& hi = T(1), const T& lo = T(0));
465 
467 
472 template <class T>
473 T wrap(const T& value, long& numWraps, const T& hi = T(1), const T& lo = T(0));
474 
478 template <class T>
479 T wrapAdd1(const T& v, const T& max) {
480  ++v;
481  return v == max ? 0 : v;
482 }
483 
487 template <class T>
488 T wrapOnce(const T& value, const T& hi = T(1));
489 
490 template <class T>
491 T wrapOnce(const T& value, const T& hi, const T& lo);
492 
496 template <class T>
497 T wrapPhase(const T& radians);
498 
502 template <class T>
503 T wrapPhaseOnce(const T& radians);
504 
505 // Implementation
506 //------------------------------------------------------------------------------
507 
508 #define TEM template <class T>
509 
510 namespace {
511 template <class T>
512 const T roundEps();
513 template <>
514 inline const float roundEps<float>() {
515  return 0.499999925f;
516 }
517 template <>
518 inline const double roundEps<double>() {
519  return 0.499999985;
520 }
521 
522 inline uint32_t deBruijn(uint32_t v) {
523  static const uint32_t deBruijnBitPosition[32] = {
524  0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
525  31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9};
526  return deBruijnBitPosition[(uint32_t(v * 0x077CB531UL)) >> 27];
527 }
528 
529 const uint32_t mFactorial12u[13] = {1, 1, 2, 6, 24,
530  120, 720, 5040, 40320, 362880,
531  3628800, 39916800, 479001600};
532 
533 const uint8_t mPrimes54[54] = {
534  /* 0 1 2 3 4 5 6 7 8 9 */
535  2, 3, 5, 7, 11, 13, 17, 19, 23, 29, // 0
536  31, 37, 41, 43, 47, 53, 59, 61, 67, 71, // 1
537  73, 79, 83, 89, 97, 101, 103, 107, 109, 113, // 2
538  127, 131, 137, 139, 149, 151, 157, 163, 167, 173, // 3
539  179, 181, 191, 193, 197, 199, 211, 223, 227, 229, // 4
540  233, 239, 241, 251 // 5
541 };
542 } // namespace
543 
544 inline bool aeq(float a, float b, int maxULP) {
545  // Make sure maxULP is non-negative and small enough that the
546  // default NAN won't compare as equal to anything.
547  // assert(maxULP > 0 && maxULP < 4 * 1024 * 1024);
548  union {
549  float f;
550  int32_t i;
551  } u;
552  u.f = a;
553  int32_t ai = u.i;
554  u.f = b;
555  int32_t bi = u.i;
556  // Make ai and bi lexicographically ordered as a twos-complement int
557  if (ai < 0) ai = 0x80000000 - ai;
558  if (bi < 0) bi = 0x80000000 - bi;
559  return std::abs((float)(ai - bi)) <= maxULP;
560 }
561 
562 inline bool aeq(double a, double b, int maxULP) {
563  // Make sure maxULP is non-negative and small enough that the
564  // default NAN won't compare as equal to anything.
565  // assert(maxULP > 0 && maxULP < 4 * 1024 * 1024);
566  union {
567  double f;
568  int64_t i;
569  } u;
570  u.f = a;
571  int64_t ai = u.i;
572  u.f = b;
573  int64_t bi = u.i;
574  // Make ai and bi lexicographically ordered as a twos-complement int
575  if (ai < 0) ai = 0x8000000000000000ULL - ai;
576  if (bi < 0) bi = 0x8000000000000000ULL - bi;
577  return std::abs((double)(ai - bi)) <= maxULP;
578 }
579 
580 TEM inline T atLeast(const T& v, const T& e) {
581  return (v >= T(0)) ? std::max(v, e) : std::min(v, -e);
582 }
583 
584 TEM T atan2Fast(const T& y, const T& x) {
585  T r, angle;
586  T ay = std::abs(y) + T(1e-10); // kludge to prevent 0/0 condition
587 
588  if (x < T(0)) {
589  r = (x + ay) / (ay - x);
590  angle = T(M_3PI_4);
591  } else {
592  r = (x - ay) / (x + ay);
593  angle = T(M_PI_4);
594  }
595 
596  angle += (T(0.1963) * r * r - T(0.9817)) * r;
597  return y < T(0) ? -angle : angle;
598 }
599 
600 inline uint32_t bitsSet(uint32_t v) {
601  v = v - ((v >> 1) & 0x55555555); // reuse input as temporary
602  v = (v & 0x33333333) + ((v >> 2) & 0x33333333); // temp
603  return ((v + ((v >> 4) & 0xF0F0F0F)) * 0x1010101) >> 24; // count
604 }
605 
606 TEM inline T ceil(const T& v, const T& s) { return std::ceil(v / s) * s; }
607 TEM inline T ceil(const T& v, const T& s, const T& r) {
608  return std::ceil(v * r) * s;
609 }
610 
611 inline uint32_t ceilPow2(uint32_t v) {
612  --v;
613  v |= v >> 1;
614  v |= v >> 2;
615  v |= v >> 4;
616  v |= v >> 8;
617  v |= v >> 16;
618  return v + 1;
619 }
620 
621 TEM inline T clip(const T& v, const T& hi, const T& lo) {
622  if (v < lo)
623  return lo;
624  else if (v > hi)
625  return hi;
626  return v;
627 }
628 
629 TEM inline T clip(const T& v, int& clipFlag, const T& hi, const T& lo) {
630  clipFlag = 0;
631  if (v < lo) {
632  clipFlag = -1;
633  return lo;
634  } else if (v > hi) {
635  clipFlag = 1;
636  return hi;
637  }
638  return v;
639 }
640 
641 TEM inline T clipS(const T& v, const T& hi) { return al::clip(v, hi, -hi); }
642 
643 TEM inline bool even(const T& v) { return 0 == al::odd(v); }
644 
646 TEM inline T erf(const T& x) {
647  static T a = 0.147;
648  const T x2 = x * x;
649  const T ax2 = a * x2;
650  return al::sgn(x) *
651  std::sqrt(T(1) - std::exp(-x2 * (T(4. / M_PI) + ax2) / (T(1) + ax2)));
652 }
653 
654 inline uint32_t factorial(uint32_t v) { return mFactorial12u[v]; }
655 
656 inline double factorialSqrt(int v) {
657  if (v <= 1) return 1;
658  double r = 1;
659  for (int i = 2; i <= v; ++i) r *= std::sqrt(i);
660  return r;
661 }
662 
663 TEM inline T floor(const T& v, const T& s) { return std::floor(v / s) * s; }
664 TEM inline T floor(const T& v, const T& s, const T& r) {
665  return std::floor(v * r) * s;
666 }
667 
668 inline uint32_t floorPow2(uint32_t v) {
669  v |= v >> 1;
670  v |= v >> 2;
671  v |= v >> 4;
672  v |= v >> 8;
673  v |= v >> 16;
674  return (v >> 1) + 1;
675 }
676 
677 TEM inline T fold(const T& v, const T& hi, const T& lo) {
678  long numWraps;
679  T R = al::wrap(v, numWraps, hi, lo);
680  if (numWraps & 1) R = hi + lo - R;
681  return R;
682 }
683 
684 TEM inline T foldOnce(const T& v, const T& hi, const T& lo) {
685  if (v > hi) return hi + (hi - v);
686  if (v < lo) return lo + (lo - v);
687  return v;
688 }
689 
690 TEM inline T gaussian(const T& v) { return std::exp(-v * v); }
691 
692 TEM T gcd(const T& x, const T& y) {
693  if (y == T(0)) return std::abs(x);
694  return al::gcd(y, static_cast<T>(std::remainder(x, y)));
695 }
696 
698 TEM T gudermannian(const T& x) { return T(2) * std::atan(exp(x)) - T(M_PI_2); }
699 
700 TEM T laguerreL(int n, int k, T x) {
701  // T res = 1, bin = 1;
702  //
703  // for(int i=n; i>=1; --i){
704  // bin = bin * (k+i) / (n + 1 - i);
705  // res = bin - x * res / i;
706  // }
707  // return res;
708 
709  if (n < 0) return T(0);
710 
711  T L1 = 0, R = 1;
712  for (int i = 1; i <= n; ++i) {
713  T L0 = L1;
714  L1 = R;
715  R = ((2 * i + k - 1 - x) * L1 - (i + k - 1) * L0) / i;
716  }
717  return R;
718 }
719 
720 TEM inline T lcm(const T& x, const T& y) { return (x * y) / al::gcd(x, y); }
721 
722 TEM T legendreP(int l, int m, T ct, T st) {
723  switch (l) {
724  case 0:
725  return 1.;
726 
727  case 1:
728  switch (m) {
729  case 0:
730  return ct;
731  case 1:
732  return -st;
733  default:
734  return 0.;
735  }
736 
737  case 2:
738  switch (m) {
739  case 0:
740  return -0.5 + 1.5 * ct * ct;
741  case 1:
742  return -3.0 * ct * st;
743  case 2:
744  return 3.0 * st * st;
745  default:
746  return 0.;
747  }
748 
749  case 3:
750  switch (m) {
751  case 0:
752  return ct * (-1.5 + 2.5 * ct * ct);
753  case 1:
754  return (1.5 - 7.5 * ct * ct) * st;
755  case 2:
756  return 15. * ct * st * st;
757  case 3:
758  return -15. * st * st * st;
759  default:
760  return 0.;
761  }
762 
763  case 4:
764  switch (m) {
765  case 0:
766  ct *= ct;
767  return 0.375 + ct * (-3.75 + 4.375 * ct);
768  case 1:
769  return ct * (7.5 - 17.5 * ct * ct) * st;
770  case 2:
771  return (-7.5 + 52.5 * ct * ct) * st * st;
772  case 3:
773  return -105. * ct * st * st * st;
774  case 4:
775  st *= st;
776  return 105. * st * st;
777  default:
778  return 0.;
779  }
780 
781  default:;
782  }
783 
784  // if(l<0){ /*printf("l=%d. l must be non-negative.\n");*/ return 0; }
785  // if(m<-l || m>l){ /*printf("m=%d. m must be -l <= m <= l.\n");*/ return 0;
786  // }
787 
788  // First compute answer for |m|
789 
790  // compute P_l^m(x) by the recurrence relation
791  // (l-m)P_l^m(x) = x(2l-1)P_{l-1}^m(x) - (l+m-1)P_{l-2}^m(x)
792  // with
793  // P_m^m(x) = (-1)^m (2m-1)!! (1-x)^{m/2},
794  // P_{m+1}^m(x) = x(2m+1) P_m^m(x).
795 
796  T P = 0; // the result
797  int M = std::abs((double)m); // M = |m|
798  T y1 = 1.; // recursion state variable
799 
800  for (int i = 1; i <= M; ++i) y1 *= -((i << 1) - 1) * st;
801 
802  if (l == M)
803  P = y1;
804 
805  else {
806  T y = ((M << 1) + 1) * ct * y1;
807  if (l == (M + 1))
808  P = y;
809 
810  else {
811  T c = (M << 1) - 1;
812  for (int k = M + 2; k <= l; ++k) {
813  T y2 = y1;
814  y1 = y;
815  T d = c / (k - M);
816  y = (2. + d) * ct * y1 - (1. + d) * y2;
817  }
818  P = y;
819  }
820  }
821 
822  // // In the case that m<0,
823  // // compute P_n^{-|m|}(x) by the formula
824  // // P_l^{-|m|}(x) = (-1)^{|m|}((l-|m|)!/(l+|m|)!)^{1/2} P_l^{|m|}(x).
825  // // NOTE: when l and |m| are large, we risk numerical underflow...
826  // if(m<0){
827  // for(int i=l-M+1; i<=l+M; ++i) P *= 1. / i;
828  // if(al::odd(M)) P = -P;
829  // }
830 
831  return P;
832 }
833 
834 TEM T legendreP(int l, int m, T t) {
835  return al::legendreP(l, m, std::cos(t), std::sin(t));
836 }
837 
838 TEM inline bool lessAbs(const T& v, const T& eps) { return std::abs(v) < eps; }
839 
840 TEM inline T max(const T& v1, const T& v2, const T& v3) {
841  return std::max(std::max(v1, v2), v3);
842 }
843 TEM inline T mean(const T& v1, const T& v2) { return (v1 + v2) * T(0.5); }
844 TEM inline T min(const T& v1, const T& v2, const T& v3) {
845  return std::min(std::min(v1, v2), v3);
846 }
847 
848 #ifdef __MSYS__
849 // MSYS2 does not support C++11 std::nextafter like it should
850 template <class T>
851 inline T nextAfter(const T& x, const T& y) {
852  return x < y ? x + 1 : x - 1;
853 }
854 template <>
855 inline float nextAfter(const float& x, const float& y) {
856  return nextafterf(x, y);
857 }
858 template <>
859 inline double nextAfter(const double& x, const double& y) {
860  return nextafter(x, y);
861 }
862 #else
863 TEM inline T nextAfter(const T& x, const T& y) { return std::nextafter(x, y); }
864 #endif
865 
866 TEM inline T nextMultiple(T v, T m) {
867  uint32_t div = (uint32_t)(v / m);
868  return T(div + 1) * m;
869 }
870 
871 TEM inline T numInt(const T& v) { return std::floor(std::log10(v)) + 1; }
872 
873 TEM inline bool odd(const T& v) { return v & T(1); }
874 
875 TEM inline T poly(const T& v, const T& a0, const T& a1, const T& a2) {
876  return a0 + v * (a1 + v * a2);
877 }
878 TEM inline T poly(const T& v, const T& a0, const T& a1, const T& a2, T a3) {
879  return a0 + v * (a1 + v * (a2 + v * a3));
880 }
881 
882 TEM inline T pow2(const T& v) { return v * v; }
883 TEM inline T pow2S(const T& v) { return v * std::abs(v); }
884 TEM inline T pow3(const T& v) { return v * v * v; }
885 TEM inline T pow3Abs(const T& v) { return std::abs(pow3(v)); }
886 TEM inline T pow4(const T& v) { return pow2(pow2(v)); }
887 TEM inline T pow5(const T& v) { return v * pow4(v); }
888 TEM inline T pow6(const T& v) { return pow3(pow2(v)); }
889 TEM inline T pow8(const T& v) { return pow4(pow2(v)); }
890 TEM inline T pow16(const T& v) { return pow4(pow4(v)); }
891 TEM inline T pow64(const T& v) { return pow8(pow8(v)); }
892 
893 TEM inline T powN(T base, unsigned power) {
894  switch (power) {
895  case 0:
896  return T(1);
897  case 1:
898  return base;
899  case 2:
900  return pow2(base);
901  case 3:
902  return pow3(base);
903  case 4:
904  return pow4(base);
905  case 5:
906  return pow5(base);
907  case 6:
908  return pow6(base);
909  case 7:
910  return pow6(base) * base;
911  case 8:
912  return pow8(base);
913  case 9:
914  return pow8(base) * base;
915  default: {
916  T r = pow8(base) * pow2(base);
917  for (unsigned i = 10; i < power; ++i) r *= base;
918  return r;
919  }
920  }
921 }
922 
923 inline uint8_t prime(uint32_t n) { return mPrimes54[n]; }
924 
925 TEM inline T round(const T& v, const T& s) { return std::round(v / s) * s; }
926 TEM inline T round(const T& v, const T& s, const T& r) {
927  return std::round(v * r) * s;
928 }
929 TEM inline T roundAway(const T& v) {
930  return v < T(0) ? al::floor(v) : al::ceil(v);
931 }
932 TEM inline T roundAway(const T& v, const T& s) {
933  return v < T(0) ? al::floor(v, s) : al::ceil(v, s);
934 }
935 
936 TEM inline T sgn(const T& v, const T& norm) {
937  return v == T(0) ? T(0) : v < T(0) ? -norm : norm;
938 }
939 
940 TEM inline T sinc(const T& r, const T& eps) {
941  return (std::abs(r) > eps) ? std::sin(r) / r : std::cos(r);
942 }
943 
944 TEM inline T slope(const T& x1, const T& y1, const T& x2, const T& y2) {
945  return (y2 - y1) / (x2 - x1);
946 }
947 
948 TEM inline void sort(T& v1, T& v2) {
949  if (v1 > v2) {
950  T t = v1;
951  v1 = v2;
952  v2 = t;
953  }
954 }
955 
956 TEM inline T sumOfSquares(T n) {
957  static const T c1_6 = 1 / T(6);
958  static const T c2_6 = c1_6 * T(2);
959  return n * (n + 1) * (c2_6 * n + c1_6);
960 }
961 
962 inline uint32_t trailingZeroes(uint32_t v) { return deBruijn(v & -v); }
963 
964 TEM inline T trunc(const T& v, const T& s) { return std::trunc(v / s) * s; }
965 TEM inline T trunc(const T& v, const T& s, const T& r) {
966  return std::trunc(v * r) * s;
967 }
968 
969 TEM inline bool within(const T& v, const T& lo, const T& hi) {
970  return !((v < lo) || (v > hi));
971 }
972 TEM inline bool withinIE(const T& v, const T& lo, const T& hi) {
973  return (!(v < lo)) && (v < hi);
974 }
975 
976 TEM inline bool within3(const T& v1, const T& v2, const T& v3, const T& lo,
977  const T& hi) {
978  return al::within(v1, lo, hi) && al::within(v2, lo, hi) &&
979  al::within(v3, lo, hi);
980 }
981 
982 // TODO: fuse the following two functions
983 TEM inline T wrap(const T& v, const T& hi, const T& lo) {
984  if (lo == hi) return lo;
985 
986  T R = v;
987  T diff = hi - lo;
988 
989  if (R >= hi) {
990  R -= diff;
991  if (R >= hi) R -= diff * uint32_t((R - lo) / diff);
992  } else if (R < lo) {
993  R += diff;
994 
995  // If value is very slightly less than 'lo', then less significant
996  // digits might get truncated by adding a larger number.
997  if (R == diff) return al::nextAfter(R, lo);
998 
999  if (R < lo) R += diff * uint32_t(((lo - R) / diff) + 1);
1000  if (R == diff) return lo;
1001  }
1002  return R;
1003 }
1004 
1005 TEM inline T wrap(const T& v, long& numWraps, const T& hi, const T& lo) {
1006  if (lo == hi) {
1007  numWraps = 0xFFFFFFFF;
1008  return lo;
1009  }
1010 
1011  T R = v;
1012  T diff = hi - lo;
1013  numWraps = 0;
1014 
1015  if (R >= hi) {
1016  R -= diff;
1017  if (R >= hi) {
1018  numWraps = long((R - lo) / diff);
1019  R -= diff * numWraps;
1020  }
1021  ++numWraps;
1022  } else if (R < lo) {
1023  R += diff;
1024  if (R < lo) {
1025  numWraps = long((R - lo) / diff) - 1;
1026  R -= diff * numWraps;
1027  }
1028  --numWraps;
1029  }
1030  return R;
1031 }
1032 
1033 TEM inline T wrapOnce(const T& v, const T& hi) {
1034  if (v >= hi)
1035  return v - hi;
1036  else if (v < T(0))
1037  return v + hi;
1038  return v;
1039 }
1040 
1041 TEM inline T wrapOnce(const T& v, const T& hi, const T& lo) {
1042  if (v >= hi)
1043  return v - hi + lo;
1044  else if (v < lo)
1045  return v + hi - lo;
1046  return v;
1047 }
1048 
1049 TEM inline T wrapPhase(const T& r_) {
1050  // The result is [r+pi - 2pi floor([r+pi] / 2pi)] - pi
1051  // which simplified is r - 2pi floor([r+pi] / 2pi) .
1052  T r = r_;
1053  if (r >= T(M_PI)) {
1054  r -= T(M_2PI);
1055  if (r < T(M_PI)) return r;
1056  return r - T(long((r + M_PI) * M_1_2PI)) * M_2PI;
1057  } else if (r < T(-M_PI)) {
1058  r += T(M_2PI);
1059  if (r >= T(-M_PI)) return r;
1060  return r - T(long((r + M_PI) * M_1_2PI) - 1) * M_2PI;
1061  } else
1062  return r;
1063 }
1064 
1065 TEM inline T wrapPhaseOnce(const T& r) {
1066  if (r >= T(M_PI))
1067  return r - T(M_2PI);
1068  else if (r < T(-M_PI))
1069  return r + T(M_2PI);
1070  return r;
1071 }
1072 
1073 TEM inline T mapRange(T value, T inlow, T inhigh, T outlow, T outhigh) {
1074  float tmp = (value - inlow) / (inhigh - inlow);
1075  return tmp * (outhigh - outlow) + outlow;
1076 }
1077 
1078 TEM inline T lerp(T src, T dest, T amt) {
1079  return src * (T(1) - amt) + dest * amt;
1080 }
1081 
1082 #undef TEM
1083 } // namespace al
1084 #endif
T wrapAdd1(const T &v, const T &max)
T nextAfter(const T &x, const T &y)
T dBToAmp(const T &db)
T clip(const T &value, const T &hi=T(1), const T &lo=T(0))
T gaussian(const T &v)
T min(const T &v1, const T &v2, const T &v3)
uint32_t bitsSet(uint32_t v)
Returns number of bits set to 1.
void sort(T &value1, T &value2)
bool even(const T &v)
T round(const T &v, const T &step)
uint32_t factorial(uint32_t n0to12)
bool withinIE(const T &v, const T &lo, const T &hi)
T gcd(const T &x, const T &y)
T wrapPhase(const T &radians)
T mean(const T &v1, const T &v2)
T sgn(const T &v, const T &norm=T(1))
uint32_t trailingZeroes(uint32_t v)
Returns number of trailing zeros in 32-bit int.
T roundAway(const T &v)
T sumOfSquares(T n)
T ceil(const T &val, const T &step)
T numInt(const T &v)
T floor(const T &val, const T &step)
uint32_t ceilPow2(uint32_t value)
Returns power of two ceiling of value.
T wrapOnce(const T &value, const T &hi=T(1))
unsigned char prime(uint32_t n)
bool odd(const T &v)
T max(const T &v1, const T &v2, const T &v3)
bool lessAbs(const T &v, const T &eps=T(0.000001))
T laguerreL(int n, int k, T x)
Generalized Laguerre polynomial L{n,k}.
T wrapPhaseOnce(const T &radians)
bool within3(const T &v1, const T &v2, const T &v3, const T &lo, const T &hi)
T powN(T base, unsigned power)
Returns value to a positive integer power.
T nearestDiv(T of, T to)
T erf(const T &v)
T slope(const T &x1, const T &y1, const T &x2, const T &y2)
T legendreP(int l, int m, T t)
T sinc(const T &radians, const T &eps=T(0.0001))
T trunc(const T &v, const T &step)
T foldOnce(const T &value, const T &hi=T(1), const T &lo=T(0))
double factorialSqrt(int v)
T wrap(const T &value, const T &hi=T(1), const T &lo=T(0))
T fold(const T &value, const T &hi=T(1), const T &lo=T(0))
Returns value folded into [lo, hi].
T nextMultiple(T val, T multiple)
T round(const T &v, const T &step, const T &recStep)
T gudermannian(const T &x)
T ampTodB(const T &amp)
uint32_t floorPow2(uint32_t value)
Returns power of two floor of value.
T trunc(const T &v, const T &step, const T &recStep)
bool within(const T &v, const T &lo, const T &hi)
T clipS(const T &value, const T &hi=T(1))
bool aeq(float a, float b, int maxULP=10)
Return whether two floats are almost equal.
T atLeast(const T &v, const T &eps)
T atan2Fast(const T &y, const T &x)
T poly(const T &x, const T &a0, const T &a1, const T &a2)
Definition: al_App.hpp:23
uint32_t ceilEven(uint32_t v)
Returns even number ceiling.
T pow8(const T &v)
Returns value to the 8th power.
T pow6(const T &v)
Returns value to the 6th power.
T pow2S(const T &v)
Returns value to the 2nd power preserving sign.
T pow16(const T &v)
Returns value to the 16th power.
T angle(const Vec< N, T > &a, const Vec< N, T > &b)
Returns angle, in interval [0, pi], between two vectors.
Definition: al_Vec.hpp:634
T pow5(const T &v)
Returns value to the 5th power.
T pow2(const T &v)
Returns value to the 2nd power.
T pow3Abs(const T &v)
Returns absolute value to the 3rd power.
T lcm(const T &x, const T &y)
Returns least common multiple.
T pow4(const T &v)
Returns value to the 4th power.
T pow3(const T &v)
Returns value to the 3rd power.
T pow64(const T &v)
Returns value to the 64th power.