BEAST - Free Software Audio Synthesizer and Tracker  0.9.2
bsemath.hh
Go to the documentation of this file.
1  // Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl.html
2 #ifndef __BSE_MATH_H__
3 #define __BSE_MATH_H__
4 
5 #include <bse/bsedefs.hh>
6 #include <bse/bseieee754.hh> /* provides math.h */
7 
8 G_BEGIN_DECLS
9 
10 /* --- constants --- */
11 /* PI is defined in bseieee754.hh */
12 #define BSE_1_DIV_PI (0.3183098861837906715377675267450287240689) // 1/pi
13 #define BSE_PI_DIV_2 (1.570796326794896619231321691639751442099) // pi/2
14 #define BSE_2_DIV_PI (0.6366197723675813430755350534900574481378) // 2/pi
15 #define BSE_2_DIV_SQRT_PI (1.128379167095512573896158903121545171688) // 2/sqrt(pi)
16 #define BSE_2_DIV_LN2 (2.88539008177792681471984936200378427485329) // 2/ln(2)
17 #define BSE_PI_DIV_4 (0.7853981633974483096156608458198757210493) // pi/4
18 #define BSE_E (2.718281828459045235360287471352662497757) // e^1
19 #define BSE_LOG2E (1.442695040888963407359924681001892137427) // log_2(e^1)
20 #define BSE_LOG10E (0.4342944819032518276511289189166050822944) // log_10(e^1)
21 #define BSE_LN2 (0.6931471805599453094172321214581765680755) // ln(2)
22 #define BSE_SQRT2 (1.41421356237309504880168872420969807857) // sqrt(2)
23 #define BSE_1_DIV_SQRT2 (0.7071067811865475244008443621048490392848) // 1/sqrt(2)
24 #define BSE_LN4 (1.386294361119890618834464242916353136151) // ln(4)
25 #define BSE_LN10 (2.302585092994045684017991454684364207601) // ln(10)
26 #define BSE_LOG2_10 (3.321928094887362347870319429489390175865) // log_2(10)
27 #define BSE_LOG2POW20_10 (0.1660964047443681173935159714744695087932) // log_2(10)/20
28 #define BSE_2_POW_1_DIV_12 (1.059463094359295264561825294946341700779) // 2^(1/12)
29 #define BSE_LN_2_POW_1_DIV_12 (5.776226504666210911810267678818138067296e-2) // ln(2^(1/12))
30 #define BSE_LN_2_POW_1_DIV_1200_d (5.776226504666210911810267678818138067296e-4) // ln(2^(1/1200))
31 #define BSE_2_POW_1_DIV_72 (1.009673533228510862192521401118605073603) // 2^(1/72)
32 #define BSE_LN_2_POW_1_DIV_72 (9.62704417444368485301711279803023011216e-3) // ln(2^(1/72))
33 #define BSE_DECIBEL20_FACTOR (8.68588963806503655302257837833210164588794) // 20.0 / ln (10.0)
34 #define BSE_DECIBEL10_FACTOR (4.34294481903251827651128918916605082294397) // 10.0 / ln (10.0)
35 #define BSE_1_DIV_DECIBEL20_FACTOR (0.1151292546497022842008995727342182103801) // ln (10) / 20
36 #define BSE_COMPLEX_ONE (bse_complex (1, 0))
37 
38 /* --- structures --- */
39 typedef struct {
40  double re;
41  double im;
42 } BseComplex;
43 
44 /* --- complex numbers --- */
45 static inline BseComplex bse_complex (double re,
46  double im);
47 static inline BseComplex bse_complex_polar (double abs,
48  double arg);
49 static inline BseComplex bse_complex_add (BseComplex c1,
50  BseComplex c2);
51 static inline BseComplex bse_complex_add3 (BseComplex c1,
52  BseComplex c2,
53  BseComplex c3);
54 static inline BseComplex bse_complex_sub (BseComplex c1,
55  BseComplex c2);
56 static inline BseComplex bse_complex_sub3 (BseComplex c1,
57  BseComplex c2,
58  BseComplex c3);
59 static inline BseComplex bse_complex_scale (BseComplex c1,
60  double scale);
61 static inline BseComplex bse_complex_mul (BseComplex c1,
62  BseComplex c2);
63 static inline BseComplex bse_complex_mul3 (BseComplex c1,
64  BseComplex c2,
65  BseComplex c3);
66 static inline BseComplex bse_complex_div (BseComplex a,
67  BseComplex b);
68 static inline BseComplex bse_complex_reciprocal (BseComplex c);
69 static inline BseComplex bse_complex_sqrt (BseComplex z);
70 static inline BseComplex bse_complex_conj (BseComplex c); /* {re, -im} */
71 static inline BseComplex bse_complex_id (BseComplex c);
72 static inline BseComplex bse_complex_inv (BseComplex c); /* {-re, -im} */
73 static inline double bse_complex_abs (BseComplex c);
74 static inline double bse_complex_arg (BseComplex c);
75 static inline BseComplex bse_complex_sin (BseComplex c);
76 static inline BseComplex bse_complex_cos (BseComplex c);
77 static inline BseComplex bse_complex_tan (BseComplex c);
78 static inline BseComplex bse_complex_sinh (BseComplex c);
79 static inline BseComplex bse_complex_cosh (BseComplex c);
80 static inline BseComplex bse_complex_tanh (BseComplex c);
81 std::string bse_complex_str (BseComplex c);
82 std::string bse_complex_list (uint n_points,
83  BseComplex *points,
84  const std::string &indent);
85 void bse_complex_gnuplot (const char *file_name,
86  uint n_points,
87  BseComplex *points);
88 std::string bse_string_from_double (long double value);
89 
90 /* --- polynomials --- */
91 /* example, degree=2: 5+2x+7x^2 => a[0..degree] = { 5, 2, 7 } */
92 static inline void bse_poly_add (uint degree,
93  double *a, /* a[0..degree] */
94  double *b);
95 static inline void bse_poly_sub (uint order,
96  double *a, /* [0..degree] */
97  double *b);
98 static inline void bse_poly_mul (double *p, /* out:[0..aorder+border] */
99  uint aorder,
100  const double *a, /* in:[0..aorder] */
101  uint border,
102  const double *b); /* in:[0..border] */
103 static inline void bse_poly_scale (uint order,
104  double *a, /* [0..degree] */
105  double scale);
106 static inline void bse_poly_xscale (uint order,
107  double *a, /* [0..degree] */
108  double xscale);
109 static inline double bse_poly_eval (uint degree,
110  double *a, /* [0..degree] */
111  double x);
112 void bse_poly_complex_roots (uint poly_degree,
113  double *a, /* [0..degree] (degree+1 elements) */
114  BseComplex *roots); /* [degree] */
115 void bse_poly_from_re_roots (uint poly_degree,
116  double *a, /* [0..degree] */
117  BseComplex *roots);
118 void bse_cpoly_from_roots (uint poly_degree,
119  BseComplex *c, /* [0..degree] */
120  BseComplex *roots);
121 static inline void bse_cpoly_mul_monomial (uint degree, /* _new_ degree */
122  BseComplex *c, /* in:[0..degree-1] out:[0..degree] */
123  BseComplex root); /* c(x) *= (x^1 - root) */
124 static inline void bse_cpoly_mul_reciprocal (uint degree, /* _new_ degree */
125  BseComplex *c, /* in:[0..degree-1] out:[0..degree] */
126  BseComplex root); /* c(x) *= (1 - root * x^-1) */
127 static inline void bse_cpoly_mul (BseComplex *p, /* out:[0..aorder+border] */
128  uint aorder,
129  BseComplex *a, /* in:[0..aorder] */
130  uint border,
131  BseComplex *b); /* in:[0..border] */
132 gboolean bse_poly2_droots (gdouble roots[2],
133  gdouble a,
134  gdouble b,
135  gdouble c);
136 std::string bse_poly_str (uint degree,
137  double *a,
138  const std::string &var);
139 std::string bse_poly_str1 (uint degree,
140  double *a,
141  const std::string &var);
142 
143 /* --- transformations --- */
144 double bse_temp_freq (double kammer_freq,
145  int semitone_delta);
146 
147 /* --- miscellaneous --- */
148 double bse_bit_depth_epsilon (guint n_bits); /* 1..32 */
149 gint bse_rand_int (void); /* +-G_MAXINT */
150 gfloat bse_rand_float (void); /* -1.0..1.0 */
151 gint bse_rand_bool (void); /* random bit */
152 void bse_float_gnuplot (const char *file_name,
153  double xstart,
154  double xstep,
155  uint n_ypoints,
156  const float *ypoints);
157 
158 
159 /* --- implementations --- */
160 static inline BseComplex
161 bse_complex (double re,
162  double im)
163 {
164  BseComplex r;
165  r.re = re;
166  r.im = im;
167  return r;
168 }
169 static inline BseComplex
170 bse_complex_polar (double abs,
171  double arg)
172 {
173  return bse_complex (abs * cos (arg), abs * sin (arg));
174 }
175 static inline BseComplex
176 bse_complex_add (BseComplex c1,
177  BseComplex c2)
178 {
179  return bse_complex (c1.re + c2.re, c1.im + c2.im);
180 }
181 static inline BseComplex
182 bse_complex_add3 (BseComplex c1,
183  BseComplex c2,
184  BseComplex c3)
185 {
186  return bse_complex (c1.re + c2.re + c3.re, c1.im + c2.im + c3.im);
187 }
188 static inline BseComplex
189 bse_complex_sub (BseComplex c1,
190  BseComplex c2)
191 {
192  return bse_complex (c1.re - c2.re, c1.im - c2.im);
193 }
194 static inline BseComplex
195 bse_complex_sub3 (BseComplex c1,
196  BseComplex c2,
197  BseComplex c3)
198 {
199  return bse_complex (c1.re - c2.re - c3.re, c1.im - c2.im - c3.im);
200 }
201 static inline BseComplex
202 bse_complex_scale (BseComplex c1,
203  double scale)
204 {
205  return bse_complex (c1.re * scale, c1.im * scale);
206 }
207 static inline BseComplex
208 bse_complex_mul (BseComplex c1,
209  BseComplex c2)
210 {
211  return bse_complex (c1.re * c2.re - c1.im * c2.im, c1.re * c2.im + c1.im * c2.re);
212 }
213 static inline BseComplex
214 bse_complex_mul3 (BseComplex c1,
215  BseComplex c2,
216  BseComplex c3)
217 {
218  double aec = c1.re * c2.re * c3.re;
219  double bde = c1.im * c2.im * c3.re;
220  double adf = c1.re * c2.im * c3.im;
221  double bcf = c1.im * c2.re * c3.im;
222  double ade = c1.re * c2.im * c3.re;
223  double bce = c1.im * c2.re * c3.re;
224  double acf = c1.re * c2.re * c3.im;
225  double bdf = c1.im * c2.im * c3.im;
226 
227  return bse_complex (aec - bde - adf - bcf, ade + bce + acf - bdf);
228 }
229 static inline BseComplex
230 bse_complex_div (BseComplex a,
231  BseComplex b)
232 {
233  BseComplex c;
234  if (fabs (b.re) >= fabs (b.im))
235  {
236  double r = b.im / b.re, den = b.re + r * b.im;
237  c.re = (a.re + r * a.im) / den;
238  c.im = (a.im - r * a.re) / den;
239  }
240  else
241  {
242  double r = b.re / b.im, den = b.im + r * b.re;
243  c.re = (a.re * r + a.im) / den;
244  c.im = (a.im * r - a.re) / den;
245  }
246  return c;
247 }
248 static inline BseComplex
249 bse_complex_reciprocal (BseComplex c)
250 {
251  if (fabs (c.re) >= fabs (c.im))
252  {
253  double r = c.im / c.re, den = c.re + r * c.im;
254  c.re = 1. / den;
255  c.im = - r / den;
256  }
257  else
258  {
259  double r = c.re / c.im, den = c.im + r * c.re;
260  c.re = r / den;
261  c.im = - 1. / den;
262  }
263  return c;
264 }
265 static inline BseComplex
266 bse_complex_sqrt (BseComplex z)
267 {
268  if (z.re == 0.0 && z.im == 0.0)
269  return z;
270  else
271  {
272  BseComplex c;
273  double w, x = fabs (z.re), y = fabs (z.im);
274  if (x >= y)
275  {
276  double r = y / x;
277  w = sqrt (x) * sqrt (0.5 * (1.0 + sqrt (1.0 + r * r)));
278  }
279  else
280  {
281  double r = x / y;
282  w = sqrt (y) * sqrt (0.5 * (r + sqrt (1.0 + r * r)));
283  }
284  if (z.re >= 0.0)
285  {
286  c.re = w;
287  c.im = z.im / (2.0 * w);
288  }
289  else
290  {
291  c.im = z.im >= 0 ? w : -w;
292  c.re = z.im / (2.0 * c.im);
293  }
294  return c;
295  }
296 }
297 static inline BseComplex
298 bse_complex_conj (BseComplex c)
299 {
300  return bse_complex (c.re, -c.im);
301 }
302 static inline BseComplex
303 bse_complex_inv (BseComplex c)
304 {
305  return bse_complex (-c.re, -c.im);
306 }
307 static inline BseComplex
308 bse_complex_id (BseComplex c)
309 {
310  return c;
311 }
312 static inline double
313 bse_complex_abs (BseComplex c)
314 {
315  /* compute (a^2 + b^2)^(1/2) without destructive underflow or overflow */
316  double absa = fabs (c.re), absb = fabs (c.im);
317  return (absa > absb ?
318  absb == 0.0 ? absa :
319  absa * sqrt (1.0 + (absb / absa) * (absb / absa)) :
320  absb == 0.0 ? 0.0 :
321  absb * sqrt (1.0 + (absa / absb) * (absa / absb)));
322 }
323 static inline double
324 bse_complex_arg (BseComplex c)
325 {
326  double a = atan2 (c.im, c.re);
327  return a;
328 }
329 static inline BseComplex
330 bse_complex_sin (BseComplex c)
331 {
332  return bse_complex (sin (c.re) * cosh (c.im), cos (c.re) * sinh (c.im));
333 }
334 static inline BseComplex
335 bse_complex_cos (BseComplex c)
336 {
337  return bse_complex (cos (c.re) * cosh (c.im), - sin (c.re) * sinh (c.im));
338 }
339 static inline BseComplex
340 bse_complex_tan (BseComplex c)
341 {
342  return bse_complex_div (bse_complex (tan (c.re), tanh (c.im)),
343  bse_complex (1.0, -tan (c.re) * tanh (c.im)));
344 }
345 static inline BseComplex
346 bse_complex_sinh (BseComplex c)
347 {
348  return bse_complex (sinh (c.re) * cos (c.im), cosh (c.re) * sin (c.im));
349 }
350 static inline BseComplex
351 bse_complex_cosh (BseComplex c)
352 {
353  return bse_complex (cosh (c.re) * cos (c.im), sinh (c.re) * sin (c.im));
354 }
355 static inline BseComplex
356 bse_complex_tanh (BseComplex c)
357 {
358  return bse_complex_div (bse_complex_sinh (c),
359  bse_complex_cosh (c));
360 }
361 static inline void
362 bse_poly_add (uint degree,
363  double *a,
364  double *b)
365 {
366  uint i;
367 
368  for (i = 0; i <= degree; i++)
369  a[i] += b[i];
370 }
371 static inline void
372 bse_poly_sub (uint degree,
373  double *a,
374  double *b)
375 {
376  uint i;
377 
378  for (i = 0; i <= degree; i++)
379  a[i] -= b[i];
380 }
381 static inline void
382 bse_poly_mul (double *p, /* out:[0..aorder+border] */
383  uint aorder,
384  const double *a, /* in:[0..aorder] */
385  uint border,
386  const double *b) /* in:[0..border] */
387 {
388  uint i;
389 
390  for (i = aorder + border; i > 0; i--)
391  {
392  uint j;
393  double t = 0;
394 
395  for (j = i - MIN (border, i); j <= MIN (aorder, i); j++)
396  t += a[j] * b[i - j];
397  p[i] = t;
398  }
399  p[0] = a[0] * b[0];
400 }
401 static inline void
402 bse_cpoly_mul_monomial (uint degree,
403  BseComplex *c,
404  BseComplex root)
405 {
406  uint j;
407 
408  c[degree] = c[degree - 1];
409  for (j = degree - 1; j >= 1; j--)
410  c[j] = bse_complex_sub (c[j - 1], bse_complex_mul (c[j], root));
411  c[0] = bse_complex_mul (c[0], bse_complex_inv (root));
412 }
413 static inline void
414 bse_cpoly_mul_reciprocal (uint degree,
415  BseComplex *c,
416  BseComplex root)
417 {
418  uint j;
419 
420  c[degree] = bse_complex_mul (c[degree - 1], bse_complex_inv (root));
421  for (j = degree - 1; j >= 1; j--)
422  c[j] = bse_complex_sub (c[j], bse_complex_mul (c[j - 1], root));
423  /* c[0] = c[0]; */
424 }
425 static inline void
426 bse_cpoly_mul (BseComplex *p, /* [0..aorder+border] */
427  uint aorder,
428  BseComplex *a,
429  uint border,
430  BseComplex *b)
431 {
432  uint i;
433 
434  for (i = aorder + border; i > 0; i--)
435  {
436  BseComplex t;
437  uint j;
438 
439  t = bse_complex (0, 0);
440  for (j = i - MIN (i, border); j <= MIN (aorder, i); j++)
441  t = bse_complex_add (t, bse_complex_mul (a[j], b[i - j]));
442  p[i] = t;
443  }
444  p[0] = bse_complex_mul (a[0], b[0]);
445 }
446 static inline void
447 bse_poly_scale (uint degree,
448  double *a,
449  double scale)
450 {
451  uint i;
452 
453  for (i = 0; i <= degree; i++)
454  a[i] *= scale;
455 }
456 static inline void
457 bse_poly_xscale (uint degree,
458  double *a,
459  double xscale)
460 {
461  double scale = xscale;
462  uint i;
463 
464  for (i = 1; i <= degree; i++)
465  {
466  a[i] *= scale;
467  scale *= xscale;
468  }
469 }
470 static inline double
471 bse_poly_eval (uint degree,
472  double *a,
473  double x)
474 {
475  double sum = a[degree];
476 
477  while (degree--)
478  sum = sum * x + a[degree];
479  return sum;
480 }
481 
482 G_END_DECLS
483 
484 #endif /* __BSE_MATH_H__ */ /* vim: set ts=8 sw=2 sts=2: */
cosh
sqrt
Definition: bsemath.hh:39
tanh
STL class.
sinh
fabs
atan2
sin
cos