libcm is a C development framework with an emphasis on audio signal processing applications.
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

cmMath.c 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612
  1. //| Copyright: (C) 2009-2020 Kevin Larke <contact AT larke DOT org>
  2. //| License: GNU GPL version 3.0 or above. See the accompanying LICENSE file.
  3. #include "cmPrefix.h"
  4. #include "cmGlobal.h"
  5. #include "cmRpt.h"
  6. #include "cmErr.h"
  7. #include "cmCtx.h"
  8. #include "cmMem.h"
  9. #include "cmMallocDebug.h"
  10. #include "cmFloatTypes.h"
  11. #include "cmMath.h"
  12. #include <sys/types.h> // u_char
  13. // TODO: rewrite to avoid copying
  14. // this code comes via csound source ...
  15. double cmX80ToDouble( unsigned char rate[10] )
  16. {
  17. char sign;
  18. short exp = 0;
  19. unsigned long mant1 = 0;
  20. unsigned long mant0 = 0;
  21. double val;
  22. unsigned char* p = (unsigned char*)rate;
  23. exp = *p++;
  24. exp <<= 8;
  25. exp |= *p++;
  26. sign = (exp & 0x8000) ? 1 : 0;
  27. exp &= 0x7FFF;
  28. mant1 = *p++;
  29. mant1 <<= 8;
  30. mant1 |= *p++;
  31. mant1 <<= 8;
  32. mant1 |= *p++;
  33. mant1 <<= 8;
  34. mant1 |= *p++;
  35. mant0 = *p++;
  36. mant0 <<= 8;
  37. mant0 |= *p++;
  38. mant0 <<= 8;
  39. mant0 |= *p++;
  40. mant0 <<= 8;
  41. mant0 |= *p++;
  42. /* special test for all bits zero meaning zero
  43. - else pow(2,-16383) bombs */
  44. if (mant1 == 0 && mant0 == 0 && exp == 0 && sign == 0)
  45. return 0.0;
  46. else {
  47. val = ((double)mant0) * pow(2.0,-63.0);
  48. val += ((double)mant1) * pow(2.0,-31.0);
  49. val *= pow(2.0,((double) exp) - 16383.0);
  50. return sign ? -val : val;
  51. }
  52. }
  53. // TODO: rewrite to avoid copying
  54. /*
  55. * Convert double to IEEE 80 bit floating point
  56. * Should be portable to all C compilers.
  57. * 19aug91 aldel/dpwe covered for MSB bug in Ultrix 'cc'
  58. */
  59. void cmDoubleToX80(double val, unsigned char rate[10])
  60. {
  61. char sign = 0;
  62. short exp = 0;
  63. unsigned long mant1 = 0;
  64. unsigned long mant0 = 0;
  65. unsigned char* p = (unsigned char*)rate;
  66. if (val < 0.0) { sign = 1; val = -val; }
  67. if (val != 0.0) /* val identically zero -> all elements zero */
  68. {
  69. exp = (short)(log(val)/log(2.0) + 16383.0);
  70. val *= pow(2.0, 31.0+16383.0-(double)exp);
  71. mant1 =((unsigned)val);
  72. val -= ((double)mant1);
  73. val *= pow(2.0, 32.0);
  74. mant0 =((double)val);
  75. }
  76. *p++ = ((sign<<7)|(exp>>8));
  77. *p++ = (u_char)(0xFF & exp);
  78. *p++ = (u_char)(0xFF & (mant1>>24));
  79. *p++ = (u_char)(0xFF & (mant1>>16));
  80. *p++ = (u_char)(0xFF & (mant1>> 8));
  81. *p++ = (u_char)(0xFF & (mant1));
  82. *p++ = (u_char)(0xFF & (mant0>>24));
  83. *p++ = (u_char)(0xFF & (mant0>>16));
  84. *p++ = (u_char)(0xFF & (mant0>> 8));
  85. *p++ = (u_char)(0xFF & (mant0));
  86. }
  87. bool cmIsPowerOfTwo( unsigned x )
  88. {
  89. return !( (x < 2) || (x & (x-1)) );
  90. }
  91. unsigned cmNextPowerOfTwo( unsigned val )
  92. {
  93. unsigned i;
  94. unsigned mask = 1;
  95. unsigned msb = 0;
  96. unsigned cnt = 0;
  97. // if val is a power of two return it
  98. if( cmIsPowerOfTwo(val) )
  99. return val;
  100. // next pow of zero is 2
  101. if( val == 0 )
  102. return 2;
  103. // if the next power of two can't be represented in 32 bits
  104. if( val > 0x80000000)
  105. {
  106. assert(0);
  107. return 0;
  108. }
  109. // find most sig. bit that is set - the number with only the next msb set is next pow 2
  110. for(i=0; i<31; i++,mask<<=1)
  111. if( mask & val )
  112. {
  113. msb = i;
  114. cnt++;
  115. }
  116. return 1 << (msb + 1);
  117. }
  118. unsigned cmNearPowerOfTwo( unsigned i )
  119. {
  120. unsigned vh = cmNextPowerOfTwo(i);
  121. if( vh == 2 )
  122. return vh;
  123. unsigned vl = vh / 2;
  124. if( vh - i < i - vl )
  125. return vh;
  126. return vl;
  127. }
  128. bool cmIsOddU( unsigned v ) { return v % 2 == 1; }
  129. bool cmIsEvenU( unsigned v ) { return !cmIsOddU(v); }
  130. unsigned cmNextOddU( unsigned v ) { return cmIsOddU(v) ? v : v+1; }
  131. unsigned cmPrevOddU( unsigned v ) { return cmIsOddU(v) ? v : v-1; }
  132. unsigned cmNextEvenU( unsigned v ) { return cmIsEvenU(v) ? v : v+1; }
  133. unsigned cmPrevEvenU( unsigned v ) { return cmIsEvenU(v) ? v : v-1; }
  134. unsigned cmModIncr(int idx, int delta, int maxN )
  135. {
  136. int sum = idx + delta;
  137. if( sum >= maxN )
  138. return sum - maxN;
  139. if( sum < 0 )
  140. return maxN + sum;
  141. return sum;
  142. }
  143. // modified bessel function of first kind, order 0
  144. // ref: orfandis appendix B io.m
  145. double cmBessel0( double x )
  146. {
  147. double eps = pow(10.0,-9.0);
  148. double n = 1.0;
  149. double S = 1.0;
  150. double D = 1.0;
  151. while(D > eps*S)
  152. {
  153. double T = x /(2.0*n);
  154. n = n+1;
  155. D = D * pow(T,2.0);
  156. S = S + D;
  157. }
  158. return S;
  159. }
  160. //=================================================================
  161. // The following elliptic-related function approximations come from
  162. // Parks & Burrus, Digital Filter Design, Appendix program 9, pp. 317-326
  163. // which in turn draws directly on other sources
  164. // calculate complete elliptic integral (quarter period) K
  165. // given *complimentary* modulus kc
  166. cmReal_t cmEllipK( cmReal_t kc )
  167. {
  168. cmReal_t a = 1, b = kc, c = 1, tmp;
  169. while( c > cmReal_EPSILON )
  170. {
  171. c = 0.5*(a-b);
  172. tmp = 0.5*(a+b);
  173. b = sqrt(a*b);
  174. a = tmp;
  175. }
  176. return M_PI/(2*a);
  177. }
  178. // calculate elliptic modulus k
  179. // given ratio of complete elliptic integrals r = K/K'
  180. // (solves the "degree equation" for fixed N = K*K1'/K'K1)
  181. cmReal_t cmEllipDeg( cmReal_t r )
  182. {
  183. cmReal_t q,a,b,c,d;
  184. a = b = c = 1;
  185. d = q = exp(-M_PI*r);
  186. while( c > cmReal_EPSILON )
  187. {
  188. a = a + 2*c*d;
  189. c = c*d*d;
  190. b = b + c;
  191. d = d*q;
  192. }
  193. return 4*sqrt(q)*pow(b/a,2);
  194. }
  195. // calculate arc elliptic tangent u (elliptic integral of the 1st kind)
  196. // given argument x = sc(u,k) and *complimentary* modulus kc
  197. cmReal_t cmEllipArcSc( cmReal_t x, cmReal_t kc )
  198. {
  199. cmReal_t a = 1, b = kc, y = 1/x, tmp;
  200. unsigned L = 0;
  201. while( true )
  202. {
  203. tmp = a*b;
  204. a += b;
  205. b = 2*sqrt(tmp);
  206. y -= tmp/y;
  207. if( y == 0 )
  208. y = sqrt(tmp) * 1E-10;
  209. if( fabs(a-b)/a < cmReal_EPSILON )
  210. break;
  211. L *= 2;
  212. if( y < 0 )
  213. L++;
  214. }
  215. if( y < 0 )
  216. L++;
  217. return (atan(a/y) + M_PI*L)/a;
  218. }
  219. // calculate Jacobi elliptic functions sn, cn, and dn
  220. // given argument u and *complimentary* modulus kc
  221. cmRC_t cmEllipJ( cmReal_t u, cmReal_t kc, cmReal_t* sn, cmReal_t* cn, cmReal_t* dn )
  222. {
  223. assert( sn != NULL || cn != NULL || dn != NULL );
  224. if( u == 0 )
  225. {
  226. if( sn != NULL ) *sn = 0;
  227. if( cn != NULL ) *cn = 1;
  228. if( dn != NULL ) *dn = 1;
  229. return cmOkRC;
  230. }
  231. int i;
  232. cmReal_t a,b,c,d,e,tmp,_sn,_cn,_dn;
  233. cmReal_t aa[16], bb[16];
  234. a = 1;
  235. b = kc;
  236. for( i = 0; i < 16; i++ )
  237. {
  238. aa[i] = a;
  239. bb[i] = b;
  240. tmp = (a+b)/2;
  241. b = sqrt(a*b);
  242. a = tmp;
  243. if( (a-b)/a < cmReal_EPSILON )
  244. break;
  245. }
  246. c = a/tan(u*a);
  247. d = 1;
  248. for( ; i >= 0; i-- )
  249. {
  250. e = c*c/a;
  251. c = c*d;
  252. a = aa[i];
  253. d = (e + bb[i]) / (e+a);
  254. }
  255. _sn = 1/sqrt(1+c*c);
  256. _cn = _sn*c;
  257. _dn = d;
  258. if( sn != NULL ) *sn = _sn;
  259. if( cn != NULL ) *cn = _cn;
  260. if( dn != NULL ) *dn = _dn;
  261. return cmOkRC;
  262. }
  263. //=================================================================
  264. // bilinear transform
  265. // z = (2*sr + s)/(2*sr - s)
  266. cmRC_t cmBlt( unsigned n, cmReal_t sr, cmReal_t* rp, cmReal_t* ip )
  267. {
  268. unsigned i;
  269. cmReal_t a = 2*sr,
  270. tr, ti, td;
  271. for( i = 0; i < n; i++ )
  272. {
  273. tr = rp[i];
  274. ti = ip[i];
  275. td = pow(a-tr, 2) + ti*ti;
  276. rp[i] = (a*a - tr*tr - ti*ti)/td;
  277. ip[i] = 2*a*ti/td;
  278. if( tr < -1E15 )
  279. rp[i] = 0;
  280. if( fabs(ti) > 1E15 )
  281. ip[i] = 0;
  282. }
  283. return cmOkRC;
  284. }
  285. unsigned cmHzToMidi( double hz )
  286. {
  287. float midi = 12.0 * log2(hz/13.75) + 9;
  288. if( midi < 0 )
  289. midi = 0;
  290. if( midi > 127 )
  291. midi = 127;
  292. return (unsigned)lround(midi);
  293. }
  294. float cmMidiToHz( unsigned midi )
  295. {
  296. double m = midi <= 127 ? midi : 127;
  297. return (float)( 13.75 * pow(2.0,(m - 9.0)/12.0));
  298. }
  299. //=================================================================
  300. // Floating point byte swapping
  301. // Unions used to type-pun the swapping functions and thereby
  302. // avoid strict aliasing problems with -O2. Using unions for
  303. // this purpose is apparently legal under C99 but not C++.
  304. typedef union
  305. {
  306. unsigned u;
  307. float f;
  308. } _cmMathU_t;
  309. typedef union
  310. {
  311. unsigned long long u;
  312. double f;
  313. } _cmMathUL_t;
  314. unsigned cmFfSwapFloatToUInt( float v )
  315. {
  316. assert( sizeof(float) == sizeof(unsigned));
  317. _cmMathU_t u;
  318. u.f=v;
  319. return cmSwap32(u.u);
  320. }
  321. float cmFfSwapUIntToFloat( unsigned v )
  322. {
  323. assert( sizeof(float) == sizeof(unsigned));
  324. _cmMathU_t u;
  325. u.u = cmSwap32(v);
  326. return u.f;
  327. }
  328. unsigned long long cmFfSwapDoubleToULLong( double v )
  329. {
  330. assert( sizeof(double) == sizeof(unsigned long long));
  331. _cmMathUL_t u;
  332. u.f = v;
  333. return cmSwap64(u.u);
  334. }
  335. double cmFfSwapULLongToDouble( unsigned long long v )
  336. {
  337. assert( sizeof(double) == sizeof(unsigned long long));
  338. _cmMathUL_t u;
  339. u.u = cmSwap64(v);
  340. return u.f;
  341. }
  342. int cmRandInt( int min, int max )
  343. {
  344. assert( min <= max );
  345. int offs = max - min;
  346. return min + cmMax(0,cmMin(offs,(int)round(offs * (double)rand() / RAND_MAX)));
  347. }
  348. unsigned cmRandUInt( unsigned min, unsigned max )
  349. {
  350. assert( min <= max );
  351. unsigned offs = max - min;
  352. return min + cmMax(0,cmMin(offs,(unsigned)round(offs * (double)rand() / RAND_MAX)));
  353. }
  354. float cmRandFloat( float min, float max )
  355. {
  356. assert( min <= max );
  357. float offs = max - min;
  358. return min + cmMax(0,cmMin(offs,(float)(offs * (double)rand() / RAND_MAX)));
  359. }
  360. double cmRandDouble( double min, double max )
  361. {
  362. assert( min <= max );
  363. double offs = max - min;
  364. return min + cmMax(0,cmMin(offs,(offs * (double)rand() / RAND_MAX)));
  365. }
  366. //=================================================================
  367. // Base on: http://stackoverflow.com/questions/3874627/floating-point-comparison-functions-for-c-sharp
  368. bool cmIsCloseD( double x0, double x1, double eps )
  369. {
  370. double d = fabs(x0-x1);
  371. if( x0 == x1 )
  372. return true;
  373. if( x0==0 || x1==0 || d<DBL_MIN )
  374. return d < (eps * DBL_MIN);
  375. return (d / cmMin( fabs(x0) + fabs(x1), DBL_MAX)) < eps;
  376. }
  377. bool cmIsCloseF( float x0, float x1, double eps_d )
  378. {
  379. float eps = (float)eps_d;
  380. float d = fabsf(x0-x1);
  381. if( x0 == x1 )
  382. return true;
  383. if( x0==0 || x1==0 || d<FLT_MIN )
  384. return d < (eps * FLT_MIN);
  385. return (d / cmMin( fabsf(x0) + fabsf(x1), FLT_MAX)) < eps;
  386. }
  387. bool cmIsCloseI( int x0, int x1, double eps )
  388. {
  389. if( x0 == x1 )
  390. return true;
  391. return abs(x0-x1)/(abs(x0)+abs(x1)) < eps;
  392. }
  393. bool cmIsCloseU( unsigned x0, unsigned x1, double eps )
  394. {
  395. if( x0 == x1 )
  396. return true;
  397. if( x0 > x1 )
  398. return (x0-x1)/(x0+x1) < eps;
  399. else
  400. return (x1-x0)/(x0+x1) < eps;
  401. }
  402. //=================================================================
  403. // cmLFSR() implementation based on note at bottom of:
  404. // http://www.ece.cmu.edu/~koopman/lfsr/index.html
  405. void cmLFSR( unsigned lfsrN, unsigned tapMask, unsigned seed, unsigned* yV, unsigned yN )
  406. {
  407. assert( 0 < lfsrN && lfsrN < 32 );
  408. unsigned i;
  409. for(i=0; i<yN; ++i)
  410. {
  411. if( (yV[i] = seed & 1)==1 )
  412. seed = (seed >> 1) ^ tapMask;
  413. else
  414. seed = (seed >> 1);
  415. }
  416. }
  417. bool cmMLS_IsBalanced( const unsigned* xV, int xN)
  418. {
  419. int a = 0;
  420. unsigned i;
  421. for(i=0; i<xN; ++i)
  422. if( xV[i] == 1 )
  423. ++a;
  424. return abs(a - (xN-a)) == 1;
  425. }
  426. unsigned _cmGenGoldCopy( int* y, unsigned yi, unsigned yN, unsigned* x, unsigned xN)
  427. {
  428. unsigned i;
  429. for(i=0; i<xN; ++i,++yi)
  430. y[yi] = x[i]==1 ? -1 : 1;
  431. assert(yi <= yN);
  432. return yi;
  433. }
  434. bool cmGenGoldCodes( unsigned lfsrN, unsigned poly_coeff0, unsigned poly_coeff1, unsigned goldN, int* yM, unsigned mlsN )
  435. {
  436. bool retFl = true;
  437. unsigned yi = 0;
  438. unsigned yN = goldN * mlsN;
  439. unsigned* mls0V = cmMemAllocZ(unsigned,mlsN);
  440. unsigned* mls1V = cmMemAllocZ(unsigned,mlsN);
  441. unsigned* xorV = cmMemAllocZ(unsigned,mlsN);
  442. unsigned i,j;
  443. cmLFSR(lfsrN, poly_coeff0, 1 << (lfsrN-1), mls0V, mlsN);
  444. cmLFSR(lfsrN, poly_coeff1, 1 << (lfsrN-1), mls1V, mlsN);
  445. if( cmMLS_IsBalanced(mls0V,mlsN) )
  446. yi = _cmGenGoldCopy(yM, yi, yN, mls0V, mlsN);
  447. if( yi<yN && cmMLS_IsBalanced(mls1V,mlsN) )
  448. yi = _cmGenGoldCopy(yM, yi, yN, mls1V, mlsN);
  449. for(i=0; yi < yN && i<mlsN-1; ++i )
  450. {
  451. for(j=0; j<mlsN; ++j)
  452. xorV[j] = (mls0V[j] + mls1V[ (i+j) % mlsN ]) % 2;
  453. if( cmMLS_IsBalanced(xorV,mlsN) )
  454. yi = _cmGenGoldCopy(yM,yi,yN,xorV,mlsN);
  455. }
  456. if(yi < yN )
  457. {
  458. //rc = cmErrMsg(err,kOpFailAtRC,"Gold code generation failed. Insuffient balanced pairs.");
  459. retFl = false;
  460. }
  461. cmMemFree(mls0V);
  462. cmMemFree(mls1V);
  463. cmMemFree(xorV);
  464. return retFl;
  465. }
  466. bool cmLFSR_Test()
  467. {
  468. // lfsrN = 5; % 5 6 7;
  469. // poly_coeff0 = 0x12; % 0x12 0x21 0x41;
  470. // poly_coeff1 = 0x1e; % 0x1e 0x36 0x72;
  471. unsigned lfsrN = 7;
  472. unsigned pc0 = 0x41;
  473. unsigned pc1 = 0x72;
  474. unsigned mlsN = (1 << lfsrN)-1;
  475. unsigned yN = mlsN*2;
  476. unsigned yV[ yN ];
  477. unsigned i;
  478. cmLFSR( lfsrN, pc0, 1 << (lfsrN-1), yV, yN );
  479. for(i=0; i<mlsN; ++i)
  480. if( yV[i] != yV[i+mlsN] )
  481. return false;
  482. //atVOU_PrintL(NULL,"0x12",yV,mlsN,2);
  483. cmLFSR( lfsrN, pc1, 1 << (lfsrN-1), yV, yN );
  484. //atVOU_PrintL(NULL,"0x17",yV,mlsN,2);
  485. for(i=0; i<mlsN; ++i)
  486. if( yV[i] != yV[i+mlsN] )
  487. return false;
  488. return true;
  489. }