BEAST/BSE - Better Audio System and Sound Engine  0.8.2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
bsemath.hh
Go to the documentation of this file.
00001  // Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl.html
00002 #ifndef __BSE_MATH_H__
00003 #define __BSE_MATH_H__
00004 
00005 #include <bse/bsedefs.hh>
00006 #include <bse/bseieee754.hh>    /* provides math.h */
00007 
00008 G_BEGIN_DECLS
00009 
00010 /* --- constants --- */
00011 /* PI is defined in bseieee754.hh */
00012 #define BSE_1_DIV_PI                  (0.3183098861837906715377675267450287240689)   // 1/pi
00013 #define BSE_PI_DIV_2                  (1.570796326794896619231321691639751442099)    // pi/2
00014 #define BSE_2_DIV_PI                  (0.6366197723675813430755350534900574481378)   // 2/pi
00015 #define BSE_2_DIV_SQRT_PI             (1.128379167095512573896158903121545171688)    // 2/sqrt(pi)
00016 #define BSE_2_DIV_LN2                 (2.88539008177792681471984936200378427485329)  // 2/ln(2)
00017 #define BSE_PI_DIV_4                  (0.7853981633974483096156608458198757210493)   // pi/4
00018 #define BSE_E                         (2.718281828459045235360287471352662497757)    // e^1
00019 #define BSE_LOG2E                     (1.442695040888963407359924681001892137427)    // log_2(e^1)
00020 #define BSE_LOG10E                    (0.4342944819032518276511289189166050822944)   // log_10(e^1)
00021 #define BSE_LN2                       (0.6931471805599453094172321214581765680755)   // ln(2)
00022 #define BSE_SQRT2                     (1.41421356237309504880168872420969807857)     // sqrt(2)
00023 #define BSE_1_DIV_SQRT2               (0.7071067811865475244008443621048490392848)   // 1/sqrt(2)
00024 #define BSE_LN4                       (1.386294361119890618834464242916353136151)    // ln(4)
00025 #define BSE_LN10                      (2.302585092994045684017991454684364207601)    // ln(10)
00026 #define BSE_LOG2_10                   (3.321928094887362347870319429489390175865)    // log_2(10)
00027 #define BSE_LOG2POW20_10              (0.1660964047443681173935159714744695087932)   // log_2(10)/20
00028 #define BSE_2_POW_1_DIV_12            (1.059463094359295264561825294946341700779)    // 2^(1/12)
00029 #define BSE_LN_2_POW_1_DIV_12         (5.776226504666210911810267678818138067296e-2) // ln(2^(1/12))
00030 #define BSE_LN_2_POW_1_DIV_1200_d     (5.776226504666210911810267678818138067296e-4) // ln(2^(1/1200))
00031 #define BSE_2_POW_1_DIV_72            (1.009673533228510862192521401118605073603)    // 2^(1/72)
00032 #define BSE_LN_2_POW_1_DIV_72         (9.62704417444368485301711279803023011216e-3)  // ln(2^(1/72))
00033 #define BSE_DECIBEL20_FACTOR          (8.68588963806503655302257837833210164588794)  // 20.0 / ln (10.0)
00034 #define BSE_DECIBEL10_FACTOR          (4.34294481903251827651128918916605082294397)  // 10.0 / ln (10.0)
00035 #define BSE_1_DIV_DECIBEL20_FACTOR    (0.1151292546497022842008995727342182103801)   // ln (10) / 20
00036 #define BSE_COMPLEX_ONE               (bse_complex (1, 0))
00037 
00038 /* --- structures --- */
00039 typedef struct {
00040   double re;
00041   double im;
00042 } BseComplex;
00043 
00044 /* --- complex numbers --- */
00045 static inline BseComplex bse_complex            (double         re,
00046                                                  double         im);
00047 static inline BseComplex bse_complex_polar      (double         abs,
00048                                                  double         arg);
00049 static inline BseComplex bse_complex_add        (BseComplex     c1,
00050                                                  BseComplex     c2);
00051 static inline BseComplex bse_complex_add3       (BseComplex     c1,
00052                                                  BseComplex     c2,
00053                                                  BseComplex     c3);
00054 static inline BseComplex bse_complex_sub        (BseComplex     c1,
00055                                                  BseComplex     c2);
00056 static inline BseComplex bse_complex_sub3       (BseComplex     c1,
00057                                                  BseComplex     c2,
00058                                                  BseComplex     c3);
00059 static inline BseComplex bse_complex_scale      (BseComplex     c1,
00060                                                  double         scale);
00061 static inline BseComplex bse_complex_mul        (BseComplex     c1,
00062                                                  BseComplex     c2);
00063 static inline BseComplex bse_complex_mul3       (BseComplex     c1,
00064                                                  BseComplex     c2,
00065                                                  BseComplex     c3);
00066 static inline BseComplex bse_complex_div        (BseComplex     a,
00067                                                  BseComplex     b);
00068 static inline BseComplex bse_complex_reciprocal (BseComplex     c);
00069 static inline BseComplex bse_complex_sqrt       (BseComplex     z);
00070 static inline BseComplex bse_complex_conj       (BseComplex     c); /* {re, -im} */
00071 static inline BseComplex bse_complex_id         (BseComplex     c);
00072 static inline BseComplex bse_complex_inv        (BseComplex     c); /* {-re, -im} */
00073 static inline double     bse_complex_abs        (BseComplex     c);
00074 static inline double     bse_complex_arg        (BseComplex     c);
00075 static inline BseComplex bse_complex_sin        (BseComplex     c);
00076 static inline BseComplex bse_complex_cos        (BseComplex     c);
00077 static inline BseComplex bse_complex_tan        (BseComplex     c);
00078 static inline BseComplex bse_complex_sinh       (BseComplex     c);
00079 static inline BseComplex bse_complex_cosh       (BseComplex     c);
00080 static inline BseComplex bse_complex_tanh       (BseComplex     c);
00081 std::string              bse_complex_str        (BseComplex     c);
00082 std::string              bse_complex_list       (uint           n_points,
00083                                                  BseComplex    *points,
00084                                                  const std::string &indent);
00085 void                     bse_complex_gnuplot    (const char    *file_name,
00086                                                  uint           n_points,
00087                                                  BseComplex    *points);
00088 std::string              bse_string_from_double (long double    value);
00089 
00090 /* --- polynomials --- */
00091 /* example, degree=2: 5+2x+7x^2 => a[0..degree] = { 5, 2, 7 } */
00092 static inline void     bse_poly_add             (uint           degree,
00093                                                  double        *a, /* a[0..degree] */
00094                                                  double        *b);
00095 static inline void     bse_poly_sub             (uint           order,
00096                                                  double        *a, /* [0..degree] */
00097                                                  double        *b);
00098 static inline void     bse_poly_mul             (double        *p,  /* out:[0..aorder+border] */
00099                                                  uint           aorder,
00100                                                  const double  *a,  /* in:[0..aorder] */
00101                                                  uint           border,
00102                                                  const double  *b); /* in:[0..border] */
00103 static inline void     bse_poly_scale           (uint           order,
00104                                                  double        *a, /* [0..degree] */
00105                                                  double         scale);
00106 static inline void     bse_poly_xscale          (uint           order,
00107                                                  double        *a, /* [0..degree] */
00108                                                  double         xscale);
00109 static inline double   bse_poly_eval            (uint           degree,
00110                                                  double        *a, /* [0..degree] */
00111                                                  double         x);
00112 void                   bse_poly_complex_roots   (uint           poly_degree,
00113                                                  double        *a, /* [0..degree] (degree+1 elements) */
00114                                                  BseComplex    *roots); /* [degree] */
00115 void                   bse_poly_from_re_roots   (uint           poly_degree,
00116                                                  double        *a, /* [0..degree] */
00117                                                  BseComplex    *roots);
00118 void                   bse_cpoly_from_roots     (uint           poly_degree,
00119                                                  BseComplex    *c, /* [0..degree] */
00120                                                  BseComplex    *roots);
00121 static inline void     bse_cpoly_mul_monomial   (uint           degree, /* _new_ degree */
00122                                                  BseComplex    *c, /* in:[0..degree-1] out:[0..degree] */
00123                                                  BseComplex     root); /* c(x) *= (x^1 - root) */
00124 static inline void     bse_cpoly_mul_reciprocal (uint           degree, /* _new_ degree */
00125                                                  BseComplex    *c, /* in:[0..degree-1] out:[0..degree] */
00126                                                  BseComplex     root); /* c(x) *= (1 - root * x^-1) */
00127 static inline void     bse_cpoly_mul            (BseComplex    *p,  /* out:[0..aorder+border] */
00128                                                  uint           aorder,
00129                                                  BseComplex    *a,  /* in:[0..aorder] */
00130                                                  uint           border,
00131                                                  BseComplex    *b); /* in:[0..border] */
00132 gboolean               bse_poly2_droots         (gdouble        roots[2],
00133                                                  gdouble        a,
00134                                                  gdouble        b,
00135                                                  gdouble        c);
00136 std::string            bse_poly_str             (uint           degree,
00137                                                  double        *a,
00138                                                  const std::string &var);
00139 std::string            bse_poly_str1            (uint           degree,
00140                                                  double        *a,
00141                                                  const std::string &var);
00142 
00143 /* --- transformations --- */
00144 double                 bse_temp_freq            (double         kammer_freq,
00145                                                  int            semitone_delta);
00146 
00147 /* --- miscellaneous --- */
00148 double                 bse_bit_depth_epsilon    (guint          n_bits);  /* 1..32 */
00149 gint                   bse_rand_int             (void);                   /* +-G_MAXINT */
00150 gfloat                 bse_rand_float           (void);                   /* -1.0..1.0 */
00151 gint                   bse_rand_bool            (void);                   /* random bit */
00152 void                   bse_float_gnuplot        (const char    *file_name,
00153                                                  double         xstart,
00154                                                  double         xstep,
00155                                                  uint           n_ypoints,
00156                                                  const float   *ypoints);
00157 
00158 
00159 /* --- implementations --- */
00160 static inline BseComplex
00161 bse_complex (double re,
00162              double im)
00163 {
00164   BseComplex r;
00165   r.re = re;
00166   r.im = im;
00167   return r;
00168 }
00169 static inline BseComplex
00170 bse_complex_polar (double abs,
00171                    double arg)
00172 {
00173   return bse_complex (abs * cos (arg), abs * sin (arg));
00174 }
00175 static inline BseComplex
00176 bse_complex_add (BseComplex c1,
00177                  BseComplex c2)
00178 {
00179   return bse_complex (c1.re + c2.re, c1.im + c2.im);
00180 }
00181 static inline BseComplex
00182 bse_complex_add3 (BseComplex c1,
00183                   BseComplex c2,
00184                   BseComplex c3)
00185 {
00186   return bse_complex (c1.re + c2.re + c3.re, c1.im + c2.im + c3.im);
00187 }
00188 static inline BseComplex
00189 bse_complex_sub (BseComplex c1,
00190                  BseComplex c2)
00191 {
00192   return bse_complex (c1.re - c2.re, c1.im - c2.im);
00193 }
00194 static inline BseComplex
00195 bse_complex_sub3 (BseComplex c1,
00196                   BseComplex c2,
00197                   BseComplex c3)
00198 {
00199   return bse_complex (c1.re - c2.re - c3.re, c1.im - c2.im - c3.im);
00200 }
00201 static inline BseComplex
00202 bse_complex_scale (BseComplex c1,
00203                    double     scale)
00204 {
00205   return bse_complex (c1.re * scale, c1.im * scale);
00206 }
00207 static inline BseComplex
00208 bse_complex_mul (BseComplex c1,
00209                  BseComplex c2)
00210 {
00211   return bse_complex (c1.re * c2.re - c1.im * c2.im, c1.re * c2.im + c1.im * c2.re);
00212 }
00213 static inline BseComplex
00214 bse_complex_mul3 (BseComplex c1,
00215                   BseComplex c2,
00216                   BseComplex c3)
00217 {
00218   double aec = c1.re * c2.re * c3.re;
00219   double bde = c1.im * c2.im * c3.re;
00220   double adf = c1.re * c2.im * c3.im;
00221   double bcf = c1.im * c2.re * c3.im;
00222   double ade = c1.re * c2.im * c3.re;
00223   double bce = c1.im * c2.re * c3.re;
00224   double acf = c1.re * c2.re * c3.im;
00225   double bdf = c1.im * c2.im * c3.im;
00226 
00227   return bse_complex (aec - bde - adf - bcf, ade + bce + acf - bdf);
00228 }
00229 static inline BseComplex
00230 bse_complex_div (BseComplex a,
00231                  BseComplex b)
00232 {
00233   BseComplex c;
00234   if (fabs (b.re) >= fabs (b.im))
00235     {
00236       double r = b.im / b.re, den = b.re + r * b.im;
00237       c.re = (a.re + r * a.im) / den;
00238       c.im = (a.im - r * a.re) / den;
00239     }
00240   else
00241     {
00242       double r = b.re / b.im, den = b.im + r * b.re;
00243       c.re = (a.re * r + a.im) / den;
00244       c.im = (a.im * r - a.re) / den;
00245     }
00246   return c;
00247 }
00248 static inline BseComplex
00249 bse_complex_reciprocal (BseComplex c)
00250 {
00251   if (fabs (c.re) >= fabs (c.im))
00252     {
00253       double r = c.im / c.re, den = c.re + r * c.im;
00254       c.re = 1. / den;
00255       c.im = - r / den;
00256     }
00257   else
00258     {
00259       double r = c.re / c.im, den = c.im + r * c.re;
00260       c.re = r / den;
00261       c.im = - 1. / den;
00262     }
00263   return c;
00264 }
00265 static inline BseComplex
00266 bse_complex_sqrt (BseComplex z)
00267 {
00268   if (z.re == 0.0 && z.im == 0.0)
00269     return z;
00270   else
00271     {
00272       BseComplex c;
00273       double w, x = fabs (z.re), y = fabs (z.im);
00274       if (x >= y)
00275         {
00276           double r = y / x;
00277           w = sqrt (x) * sqrt (0.5 * (1.0 + sqrt (1.0 + r * r)));
00278         }
00279       else
00280         {
00281           double r = x / y;
00282           w = sqrt (y) * sqrt (0.5 * (r + sqrt (1.0 + r * r)));
00283         }
00284       if (z.re >= 0.0)
00285         {
00286           c.re = w;
00287           c.im = z.im / (2.0 * w);
00288         }
00289       else
00290         {
00291           c.im = z.im >= 0 ? w : -w;
00292           c.re = z.im / (2.0 * c.im);
00293         }
00294       return c;
00295     }
00296 }
00297 static inline BseComplex
00298 bse_complex_conj (BseComplex c)
00299 {
00300   return bse_complex (c.re, -c.im);
00301 }
00302 static inline BseComplex
00303 bse_complex_inv (BseComplex c)
00304 {
00305   return bse_complex (-c.re, -c.im);
00306 }
00307 static inline BseComplex
00308 bse_complex_id (BseComplex c)
00309 {
00310   return c;
00311 }
00312 static inline double
00313 bse_complex_abs (BseComplex c)
00314 {
00315   /* compute (a^2 + b^2)^(1/2) without destructive underflow or overflow */
00316   double absa = fabs (c.re), absb = fabs (c.im);
00317   return (absa > absb ?
00318           absb == 0.0 ? absa :
00319           absa * sqrt (1.0 + (absb / absa) * (absb / absa)) :
00320           absb == 0.0 ? 0.0 :
00321           absb * sqrt (1.0 + (absa / absb) * (absa / absb)));
00322 }
00323 static inline double
00324 bse_complex_arg (BseComplex c)
00325 {
00326   double a = atan2 (c.im, c.re);
00327   return a;
00328 }
00329 static inline BseComplex
00330 bse_complex_sin (BseComplex c)
00331 {
00332   return bse_complex (sin (c.re) * cosh (c.im), cos (c.re) * sinh (c.im));
00333 }
00334 static inline BseComplex
00335 bse_complex_cos (BseComplex c)
00336 {
00337   return bse_complex (cos (c.re) * cosh (c.im), - sin (c.re) * sinh (c.im));
00338 }
00339 static inline BseComplex
00340 bse_complex_tan (BseComplex c)
00341 {
00342   return bse_complex_div (bse_complex (tan (c.re), tanh (c.im)),
00343                           bse_complex (1.0, -tan (c.re) * tanh (c.im)));
00344 }
00345 static inline BseComplex
00346 bse_complex_sinh (BseComplex c)
00347 {
00348   return bse_complex (sinh (c.re) * cos (c.im), cosh (c.re) * sin (c.im));
00349 }
00350 static inline BseComplex
00351 bse_complex_cosh (BseComplex c)
00352 {
00353   return bse_complex (cosh (c.re) * cos (c.im), sinh (c.re) * sin (c.im));
00354 }
00355 static inline BseComplex
00356 bse_complex_tanh (BseComplex c)
00357 {
00358   return bse_complex_div (bse_complex_sinh (c),
00359                           bse_complex_cosh (c));
00360 }
00361 static inline void
00362 bse_poly_add (uint         degree,
00363               double      *a,
00364               double      *b)
00365 {
00366   uint         i;
00367 
00368   for (i = 0; i <= degree; i++)
00369     a[i] += b[i];
00370 }
00371 static inline void
00372 bse_poly_sub (uint         degree,
00373               double      *a,
00374               double      *b)
00375 {
00376   uint         i;
00377 
00378   for (i = 0; i <= degree; i++)
00379     a[i] -= b[i];
00380 }
00381 static inline void
00382 bse_poly_mul (double        *p,  /* out:[0..aorder+border] */
00383               uint           aorder,
00384               const double  *a,  /* in:[0..aorder] */
00385               uint           border,
00386               const double  *b)  /* in:[0..border] */
00387 {
00388   uint         i;
00389 
00390   for (i = aorder + border; i > 0; i--)
00391     {
00392       uint         j;
00393       double t = 0;
00394 
00395       for (j = i - MIN (border, i); j <= MIN (aorder, i); j++)
00396         t += a[j] * b[i - j];
00397       p[i] = t;
00398     }
00399   p[0] = a[0] * b[0];
00400 }
00401 static inline void
00402 bse_cpoly_mul_monomial (uint         degree,
00403                         BseComplex  *c,
00404                         BseComplex   root)
00405 {
00406   uint         j;
00407 
00408   c[degree] = c[degree - 1];
00409   for (j = degree - 1; j >= 1; j--)
00410     c[j] = bse_complex_sub (c[j - 1], bse_complex_mul (c[j], root));
00411   c[0] = bse_complex_mul (c[0], bse_complex_inv (root));
00412 }
00413 static inline void
00414 bse_cpoly_mul_reciprocal (uint         degree,
00415                           BseComplex  *c,
00416                           BseComplex   root)
00417 {
00418   uint         j;
00419 
00420   c[degree] = bse_complex_mul (c[degree - 1], bse_complex_inv (root));
00421   for (j = degree - 1; j >= 1; j--)
00422     c[j] = bse_complex_sub (c[j], bse_complex_mul (c[j - 1], root));
00423   /* c[0] = c[0]; */
00424 }
00425 static inline void
00426 bse_cpoly_mul (BseComplex  *p,  /* [0..aorder+border] */
00427                uint         aorder,
00428                BseComplex  *a,
00429                uint         border,
00430                BseComplex  *b)
00431 {
00432   uint         i;
00433 
00434   for (i = aorder + border; i > 0; i--)
00435     {
00436       BseComplex t;
00437       uint         j;
00438 
00439       t = bse_complex (0, 0);
00440       for (j = i - MIN (i, border); j <= MIN (aorder, i); j++)
00441         t = bse_complex_add (t, bse_complex_mul (a[j], b[i - j]));
00442       p[i] = t;
00443     }
00444   p[0] = bse_complex_mul (a[0], b[0]);
00445 }
00446 static inline void
00447 bse_poly_scale (uint         degree,
00448                 double      *a,
00449                 double       scale)
00450 {
00451   uint         i;
00452 
00453   for (i = 0; i <= degree; i++)
00454     a[i] *= scale;
00455 }
00456 static inline void
00457 bse_poly_xscale (uint         degree,
00458                  double      *a,
00459                  double       xscale)
00460 {
00461   double scale = xscale;
00462   uint         i;
00463 
00464   for (i = 1; i <= degree; i++)
00465     {
00466       a[i] *= scale;
00467       scale *= xscale;
00468     }
00469 }
00470 static inline double
00471 bse_poly_eval (uint         degree,
00472                double      *a,
00473                double       x)
00474 {
00475   double sum = a[degree];
00476 
00477   while (degree--)
00478     sum = sum * x + a[degree];
00479   return sum;
00480 }
00481 
00482 G_END_DECLS
00483 
00484 #endif /* __BSE_MATH_H__ */     /* vim: set ts=8 sw=2 sts=2: */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines