AbaKus – a complex calculator
Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

1798 Zeilen
53KB

  1. /* HMath: C++ high precision math routines
  2. Copyright (C) 2004 Ariya Hidayat <ariya.hidayat@gmail.com>
  3. Last update: November 15, 2004
  4. This file was copied from the SpeedCrunch program. Please visit
  5. http://speedcrunch.berlios.de/ for more information.
  6. This program is free software; you can redistribute it and/or
  7. modify it under the terms of the GNU General Public License
  8. as published by the Free Software Foundation; either version 2
  9. of the License, or (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program. If not, write to:
  16. The Free Software Foundation, Inc.
  17. 51 Franklin Street, Fifth Floor
  18. Boston, MA 02110-1301 USA.
  19. */
  20. #include "hmath.h"
  21. #include "number.h"
  22. #include <ctype.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #include <stdio.h>
  26. #include <tqstring.h>
  27. // internal number of decimal digits
  28. #define HMATH_MAX_PREC 150
  29. // digits used for number comparison
  30. // (not all are used, to work around propagated error problem)
  31. #define HMATH_COMPARE_PREC 70
  32. // maximum shown digits if prec is negative
  33. #define HMATH_MAX_SHOWN 20
  34. // from number.c, need to be freed somehow
  35. extern bc_num _zero_;
  36. extern bc_num _one_;
  37. extern bc_num _two_;
  38. class HNumber::Private
  39. {
  40. public:
  41. bc_num num;
  42. bool nan;
  43. };
  44. void out_of_memory(void){
  45. return;
  46. }
  47. void rt_warn(char * ,...){
  48. return;
  49. }
  50. void rt_error(char * ,...){
  51. return;
  52. }
  53. static bc_num h_create( int len = 1, int scale = 0 )
  54. {
  55. bc_num temp;
  56. temp = (bc_num) malloc( sizeof(bc_struct) );
  57. temp->n_sign = PLUS;
  58. temp->n_len = len;
  59. temp->n_scale = scale;
  60. temp->n_refs = 1;
  61. temp->n_ptr = (char*) malloc( len+scale+1 );
  62. temp->n_value = temp->n_ptr;
  63. temp->n_next = 0;
  64. memset (temp->n_ptr, 0, len+scale+1);
  65. return temp;
  66. }
  67. static void h_destroy( bc_num n )
  68. {
  69. free( n->n_ptr );
  70. free( n );
  71. }
  72. // reclaim and free one bc_num from the freelist
  73. // workaround for number.c, because it doesn't really free a number
  74. // but instead put it in the pool of unused numbers
  75. // this function will take it back from that pool and set it really free
  76. static void h_grabfree()
  77. {
  78. bc_num t = bc_new_num( 1, 0 );
  79. h_destroy( t );
  80. }
  81. // make an exact (explicit) copy
  82. static bc_num h_copy( bc_num n )
  83. {
  84. int len = n->n_len;
  85. int scale = n->n_scale;
  86. bc_num result = h_create( len, scale );
  87. memcpy( result->n_ptr, n->n_value, len+scale+1 );
  88. result->n_sign = n->n_sign;
  89. result->n_value = result->n_ptr;
  90. h_grabfree();
  91. return result;
  92. }
  93. // same as copy, but readjust decimal digits
  94. static bc_num h_rescale( bc_num n, int sc )
  95. {
  96. int len = n->n_len;
  97. int scale = MIN( sc, n->n_scale );
  98. bc_num result = h_create( len, scale );
  99. memcpy( result->n_ptr, n->n_value, len+scale+1 );
  100. result->n_sign = n->n_sign;
  101. result->n_value = result->n_ptr;
  102. h_grabfree();
  103. return result;
  104. }
  105. // convert simple string to number
  106. static bc_num h_str2num( const char* str, int scale = HMATH_MAX_PREC )
  107. {
  108. int digits, strscale;
  109. const char *ptr;
  110. char *nptr;
  111. char zero_int;
  112. /* Check for valid number and count digits. */
  113. ptr = str;
  114. digits = 0;
  115. strscale = 0;
  116. zero_int = FALSE;
  117. if ( (*ptr == '+') || (*ptr == '-')) ptr++; /* Sign */
  118. while (*ptr == '0') ptr++; /* Skip leading zeros. */
  119. while (isdigit((int)*ptr)) ptr++, digits++; /* digits */
  120. if (*ptr == '.') ptr++; /* decimal point */
  121. while (isdigit((int)*ptr)) ptr++, strscale++; /* digits */
  122. if ((*ptr != '\0') || (digits+strscale == 0))
  123. return h_create();
  124. /* Adjust numbers and allocate storage and initialize fields. */
  125. strscale = MIN(strscale, scale);
  126. if (digits == 0)
  127. {
  128. zero_int = TRUE;
  129. digits = 1;
  130. }
  131. bc_num num = h_create( digits, strscale );
  132. ptr = str;
  133. if (*ptr == '-')
  134. {
  135. num->n_sign = MINUS;
  136. ptr++;
  137. }
  138. else
  139. {
  140. num->n_sign = PLUS;
  141. if (*ptr == '+') ptr++;
  142. }
  143. while (*ptr == '0') ptr++;
  144. nptr = num->n_value;
  145. if (zero_int)
  146. {
  147. *nptr++ = 0;
  148. digits = 0;
  149. }
  150. for (;digits > 0; digits--)
  151. *nptr++ = (char)CH_VAL(*ptr++);
  152. if (strscale > 0)
  153. {
  154. ptr++;
  155. for (;strscale > 0; strscale--)
  156. *nptr++ = (char)CH_VAL(*ptr++);
  157. }
  158. return num;
  159. }
  160. // add two numbers, return newly allocated number
  161. static bc_num h_add( bc_num n1, bc_num n2 )
  162. {
  163. bc_num r = h_create();
  164. bc_add( n1, n2, &r, 1 );
  165. h_grabfree();
  166. return r;
  167. }
  168. // subtract two numbers, return newly allocated number
  169. static bc_num h_sub( bc_num n1, bc_num n2 )
  170. {
  171. bc_num r = h_create();
  172. bc_sub( n1, n2, &r, 1 );
  173. h_grabfree();
  174. return r;
  175. }
  176. // multiply two numbers, return newly allocated number
  177. static bc_num h_mul( bc_num n1, bc_num n2 )
  178. {
  179. bc_num r = h_create();
  180. bc_multiply( n1, n2, &r, HMATH_MAX_PREC );
  181. h_grabfree();
  182. return r;
  183. }
  184. // divide two numbers, return newly allocated number
  185. static bc_num h_div( bc_num n1, bc_num n2 )
  186. {
  187. bc_num r = h_create();
  188. bc_divide( n1, n2, &r, HMATH_MAX_PREC );
  189. h_grabfree();
  190. return r;
  191. }
  192. // find 10 raise to num
  193. // e.g.: when num is 5, it results 100000
  194. static bc_num h_raise10( int n )
  195. {
  196. // calculate proper factor
  197. int len = abs(n)+2;
  198. char* sf = new char[len+1];
  199. sf[len] = '\0';
  200. if( n >= 0 )
  201. {
  202. sf[0] = '1';
  203. sf[len-1] = '\0';
  204. sf[len-2] = '\0';
  205. for( int i = 0; i < n; i++ )
  206. sf[i+1] = '0';
  207. }
  208. else
  209. {
  210. sf[0] = '0'; sf[1] = '.';
  211. for( int i = 0; i < -n; i++ )
  212. sf[i+2] = '0';
  213. sf[len-1] = '1';
  214. }
  215. bc_num factor = h_str2num( sf, abs(n) );
  216. delete[] sf;
  217. return factor;
  218. }
  219. // round up to certain decimal digits
  220. static bc_num h_round( bc_num n, int prec )
  221. {
  222. // no need to round?
  223. if( prec >= n->n_scale )
  224. return h_copy( n );
  225. // example: rounding "3.14159" to 4 decimal digits means
  226. // adding 0.5e-4 to 3.14159, it becomes 3.14164
  227. // taking only 4 decimal digits, so it's now 3.1416
  228. if( prec < 0 ) prec = 0;
  229. bc_num x = h_raise10( -prec-1 );
  230. bc_num y = 0;
  231. bc_int2num( &y, 5 );
  232. bc_num z = h_mul( x, y );
  233. z->n_sign = n->n_sign;
  234. bc_num r = h_add( n, z );
  235. h_destroy( x );
  236. h_destroy( y );
  237. h_destroy( z );
  238. // only digits we are interested in
  239. bc_num v = h_rescale( r, prec );
  240. h_destroy( r );
  241. return v;
  242. }
  243. // remove trailing zeros
  244. static void h_trimzeros( bc_num num )
  245. {
  246. while( ( num->n_scale > 0 ) && ( num->n_len+num->n_scale > 0 ) )
  247. if( num->n_value[num->n_len+num->n_scale-1] == 0 )
  248. num->n_scale--;
  249. else break;
  250. }
  251. static void h_init()
  252. {
  253. static bool h_initialized = false;
  254. if( !h_initialized )
  255. {
  256. h_initialized = true;
  257. bc_init_numbers();
  258. }
  259. }
  260. HNumber::HNumber()
  261. {
  262. h_init();
  263. d = new Private;
  264. d->nan = false;
  265. d->num = h_create();
  266. }
  267. HNumber::HNumber( const HNumber& hn )
  268. {
  269. h_init();
  270. d = new Private;
  271. d->nan = false;
  272. d->num = h_create();
  273. operator=( hn );
  274. }
  275. HNumber::HNumber( int i )
  276. {
  277. h_init();
  278. d = new Private;
  279. d->nan = false;
  280. d->num = h_create();
  281. bc_int2num( &d->num, i );
  282. }
  283. HNumber::HNumber( const char* str )
  284. {
  285. h_init();
  286. d = new Private;
  287. d->nan = false;
  288. d->num = h_create();
  289. if( str )
  290. if( strlen(str) == 3 )
  291. if( tolower(str[0])=='n' )
  292. if( tolower(str[1])=='a' )
  293. if( tolower(str[2])=='n' )
  294. d->nan = true;
  295. if( str && !d->nan )
  296. {
  297. char* s = new char[ strlen(str)+1 ];
  298. strcpy( s, str );
  299. char* p = s;
  300. for( ;; p++ )
  301. {
  302. if( *p != '+' )
  303. if( *p != '-' )
  304. if( *p != '.' )
  305. if( !isdigit(*p) )
  306. break;
  307. }
  308. int expd = 0;
  309. if( ( *p == 'e' ) || ( *p == 'E' ) )
  310. {
  311. *p = '\0';
  312. expd = atoi( p+1 );
  313. }
  314. h_destroy( d->num );
  315. d->num = h_str2num( s );
  316. delete [] s;
  317. if( expd >= HMATH_MAX_PREC || // too large
  318. expd <= -HMATH_MAX_PREC ) // too small
  319. {
  320. d->nan = true;
  321. }
  322. if( expd != 0 )
  323. {
  324. bc_num factor = h_raise10( expd );
  325. bc_num nn = h_copy( d->num );
  326. h_destroy( d->num );
  327. d->num = h_mul( nn, factor );
  328. h_destroy( nn );
  329. h_destroy( factor );
  330. }
  331. h_trimzeros( d->num );
  332. }
  333. }
  334. HNumber::~HNumber()
  335. {
  336. h_destroy( d->num );
  337. delete d;
  338. }
  339. bool HNumber::isNan() const
  340. {
  341. return d->nan;
  342. }
  343. bool HNumber::isZero() const
  344. {
  345. return !d->nan && ( bc_is_zero( d->num )!=0 );
  346. }
  347. bool HNumber::isPositive() const
  348. {
  349. return !d->nan && !isNegative() && !isZero();
  350. }
  351. bool HNumber::isNegative() const
  352. {
  353. return !d->nan && ( bc_is_neg( d->num )!=0 );
  354. }
  355. HNumber HNumber::nan()
  356. {
  357. HNumber n;
  358. n.d->nan = true;
  359. return n;
  360. }
  361. HNumber& HNumber::operator=( const HNumber& hn )
  362. {
  363. d->nan = hn.d->nan;
  364. h_destroy( d->num );
  365. d->num = h_copy( hn.d->num );
  366. return *this;
  367. }
  368. HNumber HNumber::operator+( const HNumber& num ) const
  369. {
  370. if( isNan() ) return HNumber( *this );
  371. if( num.isNan() ) return HNumber( num );
  372. HNumber result;
  373. h_destroy( result.d->num );
  374. result.d->num = h_add( d->num, num.d->num );
  375. return result;
  376. }
  377. HNumber& HNumber::operator+=( const HNumber& num )
  378. {
  379. HNumber n = HNumber(*this) + num;
  380. operator=( n );
  381. return *this;
  382. }
  383. HNumber HNumber::operator-( const HNumber& num ) const
  384. {
  385. if( isNan() ) return HNumber( *this );
  386. if( num.isNan() ) return HNumber( num );
  387. HNumber result;
  388. h_destroy( result.d->num );
  389. result.d->num = h_sub( d->num, num.d->num );
  390. return result;
  391. }
  392. HNumber& HNumber::operator-=( const HNumber& num )
  393. {
  394. HNumber n = HNumber(*this) - num;
  395. operator=( n );
  396. return *this;
  397. }
  398. HNumber HNumber::operator*( const HNumber& num ) const
  399. {
  400. if( isNan() ) return HNumber( *this );
  401. if( num.isNan() ) return HNumber( num );
  402. HNumber result;
  403. h_destroy( result.d->num );
  404. result.d->num = h_mul( d->num, num.d->num );
  405. return result;
  406. }
  407. HNumber& HNumber::operator*=( const HNumber& num )
  408. {
  409. HNumber n = HNumber(*this) * num;
  410. operator=( n );
  411. return *this;
  412. }
  413. HNumber HNumber::operator/( const HNumber& num ) const
  414. {
  415. if( isNan() ) return HNumber( *this );
  416. if( num.isNan() ) return HNumber( num );
  417. HNumber result;
  418. h_destroy( result.d->num );
  419. result.d->num = h_div( d->num, num.d->num );
  420. if(num == HNumber(0))
  421. result.d->nan = true;
  422. return result;
  423. }
  424. HNumber& HNumber::operator/=( const HNumber& num )
  425. {
  426. HNumber n = HNumber(*this) / num;
  427. operator=( n );
  428. return *this;
  429. }
  430. bool HNumber::operator>( const HNumber& n ) const
  431. {
  432. return HMath::compare( *this, n ) > 0;
  433. }
  434. bool HNumber::operator<( const HNumber& n ) const
  435. {
  436. return HMath::compare( *this, n ) < 0;
  437. }
  438. bool HNumber::operator>=( const HNumber& n ) const
  439. {
  440. return HMath::compare( *this, n ) >= 0;
  441. }
  442. bool HNumber::operator<=( const HNumber& n ) const
  443. {
  444. return HMath::compare( *this, n ) <= 0;
  445. }
  446. bool HNumber::operator==( const HNumber& n ) const
  447. {
  448. return HMath::compare( *this, n ) == 0;
  449. }
  450. bool HNumber::operator!=( const HNumber& n ) const
  451. {
  452. return HMath::compare( *this, n ) != 0;
  453. }
  454. // format number with fixed number of decimal digits
  455. char* HMath::formatFixed( const HNumber& hn, int prec )
  456. {
  457. if( hn.isNan() )
  458. {
  459. char* str = (char*)malloc( 4 );
  460. str[0] = 'N';
  461. str[1] = 'a';
  462. str[2] = 'N';
  463. str[3] = '\0';
  464. return str;
  465. }
  466. bc_num n = h_copy( hn.d->num );
  467. h_trimzeros( n );
  468. int oprec = prec;
  469. if( prec < 0 )
  470. {
  471. prec = HMATH_MAX_SHOWN;
  472. if( n->n_scale < HMATH_MAX_SHOWN )
  473. prec = n->n_scale;
  474. }
  475. // yes, this is necessary!
  476. bc_num m = h_round( n, prec );
  477. h_trimzeros( m );
  478. h_destroy( n );
  479. n = m;
  480. if( oprec < 0 )
  481. {
  482. prec = HMATH_MAX_SHOWN;
  483. if( n->n_scale < HMATH_MAX_SHOWN )
  484. prec = n->n_scale;
  485. }
  486. // how many to allocate?
  487. int len = n->n_len + prec;
  488. if( n->n_sign != PLUS ) len++;
  489. if( prec > 0 ) len++;
  490. char* str = (char*)malloc( len+1 );
  491. char* p = str;
  492. // the sign and the integer part
  493. // but avoid printing "-0"
  494. if( n->n_sign != PLUS )
  495. if( !bc_is_zero( n ) ) *p++ = '-';
  496. for( int c=0; c<n->n_len; c++ )
  497. *p++ = (char)BCD_CHAR( n->n_value[c] );
  498. // the fraction part
  499. if( prec > 0 )
  500. {
  501. *p++ = '.';
  502. int k = (prec < n->n_scale) ? prec : n->n_scale;
  503. for( int d=0; d<k; d++ )
  504. *p++ = (char)BCD_CHAR( n->n_value[n->n_len+d] );
  505. for( int r=n->n_scale; r<prec; r++ )
  506. *p++ = '0';
  507. }
  508. *p = '\0';
  509. h_destroy( n );
  510. return str;
  511. }
  512. // format number with exponential
  513. char* HMath::formatExp( const HNumber& hn, int prec )
  514. {
  515. if( hn.isNan() )
  516. {
  517. char* str = (char*)malloc( 4 );
  518. str[0] = 'N';
  519. str[1] = 'a';
  520. str[2] = 'N';
  521. str[3] = '\0';
  522. return str;
  523. }
  524. // find the exponent and the factor
  525. int tzeros = 0;
  526. for( int c=0; c<hn.d->num->n_len+hn.d->num->n_scale; c++, tzeros++ )
  527. if( hn.d->num->n_value[c]!= 0 ) break;
  528. int expd = hn.d->num->n_len - tzeros - 1;
  529. // extra digits needed for the exponent part
  530. int expn = 0;
  531. for( int e = ::abs(expd); e > 0; e/=10 ) expn++;
  532. if( expd <= 0 ) expn++;
  533. // scale the number by a new factor
  534. HNumber nn = hn * HMath::raise( 10, -expd );
  535. // too close to zero?
  536. if( hn.isZero() || ( expd <= -HMATH_COMPARE_PREC ) )
  537. {
  538. nn = HNumber(0);
  539. expd = 0;
  540. expn = 1;
  541. }
  542. char* str = formatFixed( nn, prec );
  543. char* result = (char*) malloc( strlen(str)+expn+2 );
  544. strcpy( result, str );
  545. free( str );
  546. // the exponential part
  547. char* p = result + strlen(result);
  548. *p++ = 'e'; p[expn] = '\0';
  549. if( expd < 0 ) *p = '-';
  550. for( int k=expn; k>0; k-- )
  551. {
  552. int digit = expd % 10;
  553. p[k-1] = (char)('0' + ::abs( digit ));
  554. expd = expd / 10;
  555. if( expd == 0 ) break;
  556. }
  557. return result;
  558. }
  559. char* HMath::formatGeneral( const HNumber& hn, int prec )
  560. {
  561. if( hn.isNan() )
  562. {
  563. char* str = (char*)malloc( 4 );
  564. str[0] = 'N';
  565. str[1] = 'a';
  566. str[2] = 'N';
  567. str[3] = '\0';
  568. return str;
  569. }
  570. // find the exponent and the factor
  571. int tzeros = 0;
  572. for( int c=0; c<hn.d->num->n_len+hn.d->num->n_scale; c++, tzeros++ )
  573. if( hn.d->num->n_value[c]!= 0 ) break;
  574. int expd = hn.d->num->n_len - tzeros - 1;
  575. char* str;
  576. if( expd > 5 )
  577. str = formatExp( hn, prec );
  578. else if( ( expd < -4 ) && (expd>-HMATH_COMPARE_PREC ) )
  579. str = formatExp( hn, prec );
  580. else if ( (expd < 0) && (prec>0) && (expd < -prec) )
  581. str = formatExp( hn, prec );
  582. else
  583. str = formatFixed( hn, prec );
  584. return str;
  585. }
  586. TQString HMath::formatGenString( const HNumber &n, int prec )
  587. {
  588. char *foo = formatGeneral(n, prec);
  589. TQString s(foo);
  590. free(foo);
  591. return s;
  592. }
  593. char* HMath::format( const HNumber& hn, char format, int prec )
  594. {
  595. if( hn.isNan() )
  596. {
  597. char* str = (char*)malloc( 4 );
  598. str[0] = 'N';
  599. str[1] = 'a';
  600. str[2] = 'N';
  601. str[3] = '\0';
  602. return str;
  603. }
  604. if( format=='g' )
  605. return formatGeneral( hn, prec );
  606. else if( format=='f' )
  607. return formatFixed( hn, prec );
  608. else if( format=='e' )
  609. return formatExp( hn, prec );
  610. // fallback to 'g'
  611. return formatGeneral( hn, prec );
  612. }
  613. HNumber HMath::pi()
  614. {
  615. return HNumber("3.14159265358979323846264338327950288419716939937510"
  616. "58209749445923078164062862089986280348253421170679"
  617. "82148086513282306647093844609550582231725359408128"
  618. "48111745028410270193852110555964462294895493038196"
  619. "44288109756659334461284756482337867831652712019091"
  620. "45648566923460348610454326648213393607260249141273"
  621. "72458700660631558817488152092096282925409171536436"
  622. "78925903600113305305488204665213841469519415116094"
  623. "33057270365759591953092186117381932611793105118548"
  624. "07446237996274956735188575272489122793818301194912"
  625. "98336733624406566430860213949463952247371907021798"
  626. "60943702770539217176293176752384674818467669405132"
  627. "00056812714526356082778577134275778960917363717872"
  628. "14684409012249534301465495853710507922796892589235"
  629. "42019956112129021960864034418159813629774771309960"
  630. "51870721134999999837297804995105973173281609631859"
  631. "50244594553469083026425223082533446850352619311881"
  632. "71010003137838752886587533208381420617177669147303"
  633. "59825349042875546873115956286388235378759375195778"
  634. "1857780532171226806613001927876611195909216420198" );
  635. }
  636. HNumber HMath::add( const HNumber& n1, const HNumber& n2 )
  637. {
  638. HNumber result = n1 + n2;
  639. return result;
  640. }
  641. HNumber HMath::sub( const HNumber& n1, const HNumber& n2 )
  642. {
  643. HNumber result = n1 - n2;
  644. return result;
  645. }
  646. HNumber HMath::mul( const HNumber& n1, const HNumber& n2 )
  647. {
  648. HNumber result = n1 * n2;
  649. return result;
  650. }
  651. HNumber HMath::div( const HNumber& n1, const HNumber& n2 )
  652. {
  653. HNumber result = n1 / n2;
  654. return result;
  655. }
  656. int HMath::compare( const HNumber& n1, const HNumber& n2 )
  657. {
  658. if( n1.isNan() && n2.isNan() ) return 0;
  659. HNumber delta = sub( n1, n2 );
  660. delta = HMath::round( delta, HMATH_COMPARE_PREC );
  661. if( delta.isZero() ) return 0;
  662. else if( delta.isNegative() ) return -1;
  663. return 1;
  664. }
  665. HNumber HMath::abs( const HNumber& n )
  666. {
  667. HNumber r( n );
  668. r.d->num->n_sign = PLUS;
  669. return r;
  670. }
  671. HNumber HMath::negate( const HNumber& n )
  672. {
  673. if( n.isNan() || n.isZero() )
  674. return HNumber( n );
  675. HNumber result( n );
  676. result.d->num->n_sign = ( n.d->num->n_sign == PLUS ) ? MINUS : PLUS;
  677. return result;
  678. }
  679. HNumber HMath::round( const HNumber& n, int prec )
  680. {
  681. if( n.isNan() )
  682. return HNumber::nan();
  683. HNumber result;
  684. h_destroy( result.d->num );
  685. result.d->num = h_round( n.d->num, prec );
  686. return result;
  687. }
  688. HNumber HMath::integer( const HNumber& n )
  689. {
  690. if( n.isNan() )
  691. return HNumber::nan();
  692. if( n.isZero() )
  693. return HNumber( 0 );
  694. HNumber result;
  695. h_destroy( result.d->num );
  696. result.d->num = h_rescale( n.d->num, 0 );
  697. return result;
  698. }
  699. HNumber HMath::frac( const HNumber& n )
  700. {
  701. if( n.isNan() )
  702. return HNumber::nan();
  703. return n - integer(n);
  704. }
  705. HNumber HMath::sqrt( const HNumber& n )
  706. {
  707. if( n.isNan() )
  708. return HNumber::nan();
  709. if( n.isZero() )
  710. return n;
  711. if( n.isNegative() )
  712. return HNumber::nan();
  713. // useful constant
  714. HNumber half("0.5");
  715. // Use Netwon-Raphson algorithm
  716. HNumber r( 1 );
  717. for( int i = 0; i < HMATH_MAX_PREC; i++ )
  718. {
  719. HNumber q = n / r;
  720. if( r == q ) break;
  721. HNumber s = r + q;
  722. r = s * half;
  723. }
  724. return r;
  725. }
  726. HNumber HMath::raise( const HNumber& n1, int n )
  727. {
  728. if( n1.isNan() ) return n1;
  729. if( n1.isZero() ) return n1;
  730. if( n1 == HNumber(1) ) return n1;
  731. if( n == 0 ) return HNumber(1);
  732. if( n == 1 ) return n1;
  733. HNumber result = n1;
  734. for( ; n > 1; n-- ) result *= n1;
  735. for( ; n < 1; n++ ) result /= n1;
  736. return result;
  737. }
  738. HNumber HMath::raise( const HNumber& n1, const HNumber& n2 )
  739. {
  740. if( n1.isNan() ) return HNumber::nan();
  741. if( n2.isNan() ) return HNumber::nan();
  742. if( n1.isZero() ) return HNumber(0);
  743. if( n1 == HNumber(1) ) return n1;
  744. if( n2.isZero() ) return HNumber(1);
  745. if( n2 == HNumber(1) ) return n1;
  746. if( n2 == HMath::integer(n2) )
  747. {
  748. // Evil hack.
  749. char *str = HMath::format( n2 );
  750. int i = atoi(str);
  751. free (str);
  752. return HMath::raise( n1, i );
  753. }
  754. // x^y = exp( y*ln(x) )
  755. HNumber result = n2 * HMath::ln(n1);
  756. result = HMath::exp( result );
  757. return result;
  758. }
  759. HNumber HMath::exp( const HNumber& x )
  760. {
  761. if( x.isNan() )
  762. return HNumber::nan();
  763. bool negative = x.isNegative();
  764. HNumber xs = HMath::abs( x );
  765. // adjust so that x is less than 1
  766. // Taylor expansion: e^x = 1 + x + x^2/2! + x^3/3! + ...
  767. HNumber num = xs;
  768. HNumber den = 1;
  769. HNumber sum = xs + 1;
  770. // now loop to sum the series
  771. for( int i = 2; i < HMATH_MAX_PREC; i++ )
  772. {
  773. num *= xs;
  774. den *= HNumber(i);
  775. if( num.isZero() ) break;
  776. HNumber s = HMath::div( num, den );
  777. if( s.isZero() ) break;
  778. sum += s;
  779. }
  780. HNumber result = sum;
  781. if( negative )
  782. result = HMath::div( HNumber(1), result );
  783. return result;
  784. };
  785. HNumber HMath::ln( const HNumber& x )
  786. {
  787. if( x.isNan() )
  788. return HNumber::nan();
  789. if( !x.isPositive() )
  790. return HNumber::nan();
  791. // short circuit
  792. if( x == HNumber(10) )
  793. return HNumber("2.30258509299404568401799145468436420760110148862877"
  794. "29760333279009675726102948650438303813865953227795"
  795. "49054520440916779445247118780973037711833599749301"
  796. "72118016928228381938415404059160910960135436620869" );
  797. // useful constants
  798. HNumber two(2);
  799. HNumber one(1);
  800. HNumber half("0.5");
  801. // adjust so that x is between 0.5 and 2.0
  802. // use the fact that ln(x^2) = 2*ln(x)
  803. HNumber xs( x );
  804. unsigned factor = 2;
  805. while( xs >= two )
  806. {
  807. factor *= 2;
  808. xs = HMath::sqrt( xs );
  809. }
  810. while( xs <= half )
  811. {
  812. factor *= 2;
  813. xs = HMath::sqrt( xs );
  814. }
  815. // Taylor expansion: ln(x) = 2(a+a^3/3+a^5/5+...)
  816. // where a=(x-1)/(x+1)
  817. HNumber p = xs - 1;
  818. HNumber q = xs + 1;
  819. HNumber a = p / q;
  820. HNumber as = a*a;
  821. HNumber t = a;
  822. HNumber sum = a;
  823. // loop for the series (limited to avoid nasty cases)
  824. for( int i = 3; i < HMATH_MAX_PREC; i+= 2 )
  825. {
  826. t *= as;
  827. if( t.isZero() ) break;
  828. HNumber s = HMath::div( t, HNumber(i) );
  829. if( s.isZero() ) break;
  830. sum += s;
  831. }
  832. HNumber result = sum * HNumber( factor );
  833. return result;
  834. }
  835. HNumber HMath::log( const HNumber& x )
  836. {
  837. if( x.isNan() )
  838. return HNumber::nan();
  839. if( !x.isPositive() )
  840. return HNumber::nan();
  841. HNumber result = HMath::ln( x ) / HMath::ln(10);
  842. return result;
  843. }
  844. // ensure angle is within 0 to 2*pi
  845. // useful for sin, cos
  846. static HNumber simplifyAngle( const HNumber& x )
  847. {
  848. if( x.isNan() )
  849. return HNumber::nan();
  850. HNumber pi2 = HMath::pi() * 2;
  851. HNumber nn = x / pi2;
  852. HNumber xs = x - HMath::integer(nn)*pi2;
  853. if( xs.isNegative() ) xs += pi2;
  854. return xs;
  855. }
  856. HNumber HMath::sin( const HNumber& x )
  857. {
  858. if( x.isNan() )
  859. return HNumber::nan();
  860. // short circuit
  861. if( x.isZero() )
  862. return x;
  863. // adjust to small angle for speedup
  864. HNumber xs = simplifyAngle( x );
  865. // Taylor expansion: sin(x) = x - x^3/3! + x^5/5! - x^7/7! ...
  866. HNumber xsq = xs*xs;
  867. HNumber num = xs;
  868. HNumber den = 1;
  869. HNumber sum = xs;
  870. // loop for the series (limited to avoid nasty cases)
  871. for( int i = 3; i < HMATH_MAX_PREC; i+=2 )
  872. {
  873. num *= xsq;
  874. if( num.isZero() ) break;
  875. den *= HNumber(i-1);
  876. den *= HNumber(i);
  877. den = HMath::negate( den );
  878. HNumber s = HMath::div( num, den );
  879. if( s.isZero() ) break;
  880. sum += s;
  881. }
  882. HNumber result = sum;
  883. return result;
  884. }
  885. HNumber HMath::cos( const HNumber& x )
  886. {
  887. if( x.isNan() )
  888. return HNumber::nan();
  889. // short circuit
  890. if( x.isZero() )
  891. return HNumber( 1 );
  892. // adjust to small angle for speedup
  893. HNumber xs = simplifyAngle( x );
  894. // Taylor expansion: cos(x) = 1 - x^2/2! + x^4/4! - x^6/6! ...
  895. HNumber xsq = xs*xs;
  896. HNumber num = 1;
  897. HNumber den = 1;
  898. HNumber sum = 1;
  899. // loop for the series (limited to avoid nasty cases)
  900. for( int i = 2; i < HMATH_MAX_PREC; i+=2 )
  901. {
  902. num *= xsq;
  903. if( num.isZero() ) break;
  904. den *= HNumber(i-1);
  905. den *= HNumber(i);
  906. den = HMath::negate( den );
  907. HNumber s = num / den;
  908. if( s.isZero() ) break;
  909. sum += s;
  910. }
  911. HNumber result = sum;
  912. return result;
  913. }
  914. HNumber HMath::tan( const HNumber& x )
  915. {
  916. if( x.isNan() )
  917. return HNumber::nan();
  918. // tan(x) = cos(x)/sin(x)
  919. HNumber s = HMath::sin( x );
  920. if( s.isZero() )
  921. return s;
  922. HNumber c = HMath::cos( x );
  923. if( c.isZero() )
  924. return HNumber::nan();
  925. HNumber result = s / c;
  926. return result;
  927. }
  928. HNumber HMath::atan( const HNumber& x )
  929. {
  930. if( x.isNan() )
  931. return HNumber::nan();
  932. // useful constants
  933. HNumber one("1.0");
  934. HNumber c( "0.2" );
  935. // short circuit
  936. if( x == c )
  937. return HNumber("0.19739555984988075837004976519479029344758510378785"
  938. "21015176889402410339699782437857326978280372880441"
  939. "12628118073691360104456479886794239355747565495216"
  940. "30327005221074700156450155600612861855266332573187" );
  941. if( x == one )
  942. // essentially equals to HMath::pi()/4;
  943. return HNumber("0.78539816339744830961566084581987572104929234984377"
  944. "64552437361480769541015715522496570087063355292669"
  945. "95537021628320576661773461152387645557931339852032"
  946. "12027936257102567548463027638991115573723873259549" );
  947. bool negative = x.isNegative();
  948. HNumber xs = HMath::abs( x );
  949. // adjust so that x is less than c (we choose c = 0.2)
  950. // use the fact that atan(x) = atan(c) + atan((x-c)/(1+xc))
  951. HNumber factor(0);
  952. HNumber base(0);
  953. while( xs > c )
  954. {
  955. base = HMath::atan( c );
  956. factor += one;
  957. HNumber p = xs - c;
  958. HNumber q = xs * c;
  959. xs = p / (q+one);
  960. }
  961. // Taylor series: atan(x) = x - x^3/3 + x^5/5 - x^7/7 + ...
  962. HNumber num = xs;
  963. HNumber xsq = xs*xs;
  964. HNumber den = 1;
  965. HNumber sum = xs;
  966. // loop for the series (limited to avoid nasty cases)
  967. for( int i = 3; i < HMATH_MAX_PREC; i+=2 )
  968. {
  969. num *= xsq;
  970. if( num.isZero() ) break;
  971. den = HNumber(i);
  972. int n = (i-1)/2;
  973. if( n&1 ) den = HNumber(-i);
  974. HNumber s = HMath::div( num, den );
  975. if( s.isZero() ) break;
  976. sum += s;
  977. }
  978. HNumber result = factor*base + sum;
  979. if( negative ) result = HMath::negate( result );
  980. return result;
  981. };
  982. HNumber HMath::asin( const HNumber& x )
  983. {
  984. if( x.isNan() )
  985. return HNumber::nan();
  986. // asin(x) = atan(x/sqrt(1-x*x));
  987. HNumber d = HMath::sqrt( HNumber(1) - x*x );
  988. if( d.isZero() )
  989. {
  990. HNumber result = HMath::pi()/2;
  991. if( x.isNegative() )
  992. result = HMath::negate( result );
  993. return result;
  994. }
  995. HNumber result = HMath::atan( x / d );
  996. return result;
  997. };
  998. HNumber HMath::acos( const HNumber& x )
  999. {
  1000. if( x.isNan() )
  1001. return HNumber::nan();
  1002. if( x.isZero() )
  1003. return HMath::pi()/2;
  1004. // acos(x) = atan(sqrt(1-x*x)/x);
  1005. HNumber n = HMath::sqrt( HNumber(1) - x*x );
  1006. HNumber result = HMath::atan( n / x );
  1007. return result;
  1008. };
  1009. HNumber HMath::sinh( const HNumber& x )
  1010. {
  1011. if( x.isNan() )
  1012. return HNumber::nan();
  1013. // sinh(x) = 0.5*(e^x - e^(-x) )
  1014. HNumber result = HMath::exp(x) - HMath::exp( HMath::negate(x) );
  1015. result = result / 2;
  1016. return result;
  1017. }
  1018. HNumber HMath::asinh( const HNumber& x )
  1019. {
  1020. HNumber one(1);
  1021. if(x.isNan())
  1022. return HNumber::nan();
  1023. return HMath::ln(x + HMath::sqrt(x * x + one));
  1024. }
  1025. HNumber HMath::cosh( const HNumber& x )
  1026. {
  1027. if( x.isNan() )
  1028. return HNumber::nan();
  1029. // cosh(x) = 0.5*(e^x - e^(-x) )
  1030. HNumber result = HMath::exp(x) + HMath::exp( HMath::negate(x) );
  1031. result = result / 2;
  1032. return result;
  1033. }
  1034. HNumber HMath::acosh( const HNumber& x )
  1035. {
  1036. HNumber one(1), zero(0);
  1037. if(x.isNan() || x < one)
  1038. return HNumber::nan();
  1039. // We always return the positive arc hyperbolic cosine.
  1040. return HMath::ln(x + HMath::sqrt(x * x - one));
  1041. }
  1042. HNumber HMath::tanh( const HNumber& x )
  1043. {
  1044. if( x.isNan() )
  1045. return HNumber::nan();
  1046. // tanh(h) = sinh(x)/cosh(x)
  1047. HNumber c = HMath::cosh( x );
  1048. if( c.isZero() )
  1049. return HNumber::nan();
  1050. HNumber s = HMath::sinh( x );
  1051. HNumber result = s / c;
  1052. return result;
  1053. }
  1054. HNumber HMath::atanh( const HNumber& x )
  1055. {
  1056. HNumber one(1), two(2);
  1057. if(x.isNan() || HMath::abs(x) >= one)
  1058. return HNumber::nan();
  1059. return HMath::ln((one + x) / (one - x)) / two;
  1060. }
  1061. void HMath::finalize()
  1062. {
  1063. bc_free_num( &_zero_ );
  1064. bc_free_num( &_one_ );
  1065. bc_free_num( &_two_ );
  1066. free( _one_ );
  1067. free( _zero_ );
  1068. free( _two_ );
  1069. h_grabfree();
  1070. h_grabfree();
  1071. h_grabfree();
  1072. h_grabfree();
  1073. }
  1074. std::ostream& operator<<( std::ostream& s, HNumber num )
  1075. {
  1076. char* str = HMath::formatFixed( num );
  1077. s << str;
  1078. delete[] str;
  1079. return s;
  1080. }
  1081. #ifdef HMATH_TEST
  1082. #include <iostream>
  1083. #include <string.h>
  1084. static int hmath_total_tests = 0;
  1085. static int hmath_failed_tests = 0;
  1086. #define CHECK(x,y) check_value(__FILE__,__LINE__,#x,x,y)
  1087. #define CHECK_FORMAT(f,p,x,y) check_format(__FILE__,__LINE__,#x,x,f,p,y)
  1088. #define CHECK_PRECISE(x,y) check_precise(__FILE__,__LINE__,#x,x,y)
  1089. static void check_value( const char *file, int line, const char* msg,
  1090. const HNumber&n, const char* expected )
  1091. {
  1092. hmath_total_tests++;
  1093. char* result = HMath::formatFixed( n );
  1094. if( strcmp( result, expected ) )
  1095. {
  1096. hmath_failed_tests++;
  1097. std::cout << file << "["<< line <<"]: " << msg;
  1098. std::cout << " Result: " << result;
  1099. std::cout << ", ";
  1100. std::cout << "Expected: " << expected;
  1101. std::cout << std::endl;
  1102. }
  1103. free( result );
  1104. }
  1105. static void check_format( const char *file, int line, const char* msg,
  1106. const HNumber&n, char format, int prec, const char* expected )
  1107. {
  1108. hmath_total_tests++;
  1109. char* result = HMath::format( n, format, prec );
  1110. if( strcmp( result, expected ) )
  1111. {
  1112. hmath_failed_tests++;
  1113. std::cout << file << "["<< line <<"]: " << msg;
  1114. std::cout << " Result: " << result;
  1115. std::cout << ", ";
  1116. std::cout << "Expected: " << expected;
  1117. std::cout << std::endl;
  1118. }
  1119. free( result );
  1120. }
  1121. static void check_precise( const char *file, int line, const char* msg,
  1122. const HNumber&n, const char* expected )
  1123. {
  1124. hmath_total_tests++;
  1125. char* result = HMath::formatFixed( n, 50 );
  1126. if( strcmp( result, expected ) )
  1127. {
  1128. hmath_failed_tests++;
  1129. std::cout << file << "["<< line <<"]: " << msg;
  1130. std::cout << " Result: " << result;
  1131. std::cout << ", ";
  1132. std::cout << "Expected: " << expected;
  1133. std::cout << std::endl;
  1134. }
  1135. free( result );
  1136. }
  1137. void test_create()
  1138. {
  1139. CHECK( HNumber("1.0"), "1" );
  1140. CHECK( HNumber("2.0"), "2" );
  1141. CHECK( HNumber("1e-3"), "0.001" );
  1142. // too large or small
  1143. CHECK( HNumber("1e200"), "NaN" );
  1144. CHECK( HNumber("1e-200"), "NaN" );
  1145. }
  1146. void test_format()
  1147. {
  1148. // fixed decimal digits
  1149. CHECK_FORMAT( 'f', 0, HNumber("NaN"), "NaN" );
  1150. CHECK_FORMAT( 'f', 0, HNumber("0"), "0" );
  1151. CHECK_FORMAT( 'f', 0, HNumber("1.1"), "1" );
  1152. CHECK_FORMAT( 'f', 1, HNumber("2.11"), "2.1" );
  1153. CHECK_FORMAT( 'f', 2, HNumber("3.111"), "3.11" );
  1154. CHECK_FORMAT( 'f', 3, HNumber("4.1111"), "4.111" );
  1155. CHECK_FORMAT( 'f', 2, HNumber("3.14"), "3.14" );
  1156. CHECK_FORMAT( 'f', 3, HNumber("3.14"), "3.140" );
  1157. CHECK_FORMAT( 'f', 5, HNumber("3.14"), "3.14000" );
  1158. CHECK_FORMAT( 'f', 7, HNumber("3.14"), "3.1400000" );
  1159. CHECK_FORMAT( 'f', 7, HNumber("-0.001"), "-0.0010000" );
  1160. CHECK_FORMAT( 'f', 8, HNumber("-0.001"), "-0.00100000" );
  1161. CHECK_FORMAT( 'f', 9, HNumber("-0.001"), "-0.001000000" );
  1162. CHECK_FORMAT( 'f', 1, HNumber("4.001"), "4.0" );
  1163. CHECK_FORMAT( 'f', -1, HNumber("4.000000000000000000000000000000000000000000001"), "4" );
  1164. // exponential format
  1165. CHECK_FORMAT( 'e', 0, HNumber("NaN"), "NaN" );
  1166. CHECK_FORMAT( 'e', 0, HNumber("0"), "0e0" );
  1167. CHECK_FORMAT( 'e', 0, HNumber("3.14"), "3e0" );
  1168. CHECK_FORMAT( 'e', 1, HNumber("3.14"), "3.1e0" );
  1169. CHECK_FORMAT( 'e', 2, HNumber("3.14"), "3.14e0" );
  1170. CHECK_FORMAT( 'e', 3, HNumber("3.14"), "3.140e0" );
  1171. CHECK_FORMAT( 'e', 5, HNumber("3.14"), "3.14000e0" );
  1172. CHECK_FORMAT( 'e', 7, HNumber("3.14"), "3.1400000e0" );
  1173. CHECK_FORMAT( 'e', 3, HNumber("-0.001"), "-1.000e-3" );
  1174. CHECK_FORMAT( 'e', 2, HNumber("0.0001"), "1.00e-4" );
  1175. CHECK_FORMAT( 'e', 2, HNumber("0.001"), "1.00e-3" );
  1176. CHECK_FORMAT( 'e', 2, HNumber("0.01"), "1.00e-2" );
  1177. CHECK_FORMAT( 'e', 2, HNumber("0.1"), "1.00e-1" );
  1178. CHECK_FORMAT( 'e', 2, HNumber("1"), "1.00e0" );
  1179. CHECK_FORMAT( 'e', 2, HNumber("10"), "1.00e1" );
  1180. CHECK_FORMAT( 'e', 2, HNumber("100"), "1.00e2" );
  1181. CHECK_FORMAT( 'e', 2, HNumber("1000"), "1.00e3" );
  1182. CHECK_FORMAT( 'e', 2, HNumber("10000"), "1.00e4" );
  1183. CHECK_FORMAT( 'e', 2, HNumber("100000"), "1.00e5" );
  1184. CHECK_FORMAT( 'e', 2, HNumber("1000000"), "1.00e6" );
  1185. CHECK_FORMAT( 'e', 2, HNumber("10000000"), "1.00e7" );
  1186. // general format
  1187. CHECK_FORMAT( 'g', -1, HMath::pi(), "3.14159265358979323846" );
  1188. CHECK_FORMAT( 'g', 3, HNumber("0"), "0.000" );
  1189. CHECK_FORMAT( 'g', 3, HNumber("0.000000001"), "1.000e-9" );
  1190. CHECK_FORMAT( 'g', 3, HNumber("0.00000001"), "1.000e-8" );
  1191. CHECK_FORMAT( 'g', 3, HNumber("0.0000001"), "1.000e-7" );
  1192. CHECK_FORMAT( 'g', 3, HNumber("0.000001"), "1.000e-6" );
  1193. CHECK_FORMAT( 'g', 3, HNumber("0.00001"), "1.000e-5" );
  1194. CHECK_FORMAT( 'g', 3, HNumber("0.0001"), "1.000e-4" );
  1195. CHECK_FORMAT( 'g', 3, HNumber("0.001"), "0.001" );
  1196. CHECK_FORMAT( 'g', 3, HNumber("0.01"), "0.010" );
  1197. CHECK_FORMAT( 'g', 3, HNumber("0.1"), "0.100" );
  1198. CHECK_FORMAT( 'g', 3, HNumber("10"), "10.000" );
  1199. CHECK_FORMAT( 'g', 3, HNumber("100"), "100.000" );
  1200. CHECK_FORMAT( 'g', 3, HNumber("1000"), "1000.000" );
  1201. CHECK_FORMAT( 'g', 3, HNumber("10000"), "10000.000" );
  1202. CHECK_FORMAT( 'g', 3, HNumber("100000"), "100000.000" );
  1203. CHECK_FORMAT( 'g', 3, HNumber("1000000"), "1.000e6" );
  1204. CHECK_FORMAT( 'g', 3, HNumber("10000000"), "1.000e7" );
  1205. CHECK_FORMAT( 'g', 3, HNumber("100000000"), "1.000e8" );
  1206. CHECK_FORMAT( 'g', 3, HNumber("1403.1977"), "1403.198" );
  1207. CHECK_FORMAT( 'g', 3, HNumber("2604.1980"), "2604.198" );
  1208. CHECK_FORMAT( 'g', 3, HNumber("2.47e4"), "24700.000" );
  1209. }
  1210. void test_op()
  1211. {
  1212. // addition
  1213. CHECK( HNumber(0)+HNumber(0), "0" );
  1214. CHECK( HNumber(1)+HNumber(0), "1" );
  1215. CHECK( HNumber(1)+HNumber(1), "2" );
  1216. CHECK( HNumber(1)+HNumber(2), "3" );
  1217. CHECK( HNumber(1)+HNumber(10), "11" );
  1218. CHECK( HNumber(1)+HNumber(100), "101" );
  1219. CHECK( HNumber(1)+HNumber(1000), "1001" );
  1220. // subtraction
  1221. CHECK( HNumber(0)-HNumber(0), "0" );
  1222. CHECK( HNumber(1)-HNumber(0), "1" );
  1223. CHECK( HNumber(1)-HNumber(2), "-1" );
  1224. // division
  1225. CHECK( HNumber(1)/HNumber(2), "0.5" );
  1226. CHECK_PRECISE( HNumber(1)/HNumber(3), "0.33333333333333333333333333333333333333333333333333" );
  1227. CHECK_PRECISE( HNumber(2)/HNumber(3), "0.66666666666666666666666666666666666666666666666667" );
  1228. CHECK_PRECISE( HNumber(1)/HNumber(7), "0.14285714285714285714285714285714285714285714285714" );
  1229. CHECK_PRECISE( HNumber(2)/HNumber(7), "0.28571428571428571428571428571428571428571428571429" );
  1230. CHECK_PRECISE( HNumber(3)/HNumber(7), "0.42857142857142857142857142857142857142857142857143" );
  1231. CHECK_PRECISE( HNumber(4)/HNumber(7), "0.57142857142857142857142857142857142857142857142857" );
  1232. CHECK_PRECISE( HNumber(1)/HNumber(9), "0.11111111111111111111111111111111111111111111111111" );
  1233. // multiplication
  1234. CHECK( HNumber(0)*HNumber(0), "0" );
  1235. CHECK( HNumber("1.0")*HNumber("0.0"), "0" );
  1236. CHECK( HNumber(1)*HNumber(1), "1" );
  1237. CHECK( HNumber(3)*HNumber(-4), "-12" );
  1238. CHECK( HNumber(-2)*HNumber(5), "-10" );
  1239. CHECK( HNumber(6)*HNumber(7), "42" );
  1240. CHECK( HNumber("1.5")*HNumber("1.5"), "2.25" );
  1241. }
  1242. void test_functions()
  1243. {
  1244. // pi
  1245. CHECK( HMath::pi(), "3.14159265358979323846" );
  1246. CHECK_PRECISE( HMath::pi(), "3.14159265358979323846264338327950288419716939937511" );
  1247. // abs
  1248. CHECK( HMath::abs("0"), "0" );
  1249. CHECK( HMath::abs("1"), "1" );
  1250. CHECK( HMath::abs("100"), "100" );
  1251. CHECK( HMath::abs("-100"), "100" );
  1252. CHECK( HMath::abs("-3.14159"), "3.14159" );
  1253. CHECK( HMath::abs("NaN"), "NaN" );
  1254. // round
  1255. CHECK( HMath::round( "3.14" ), "3" );
  1256. CHECK( HMath::round( "1.77" ), "2" );
  1257. CHECK( HMath::round( "3.14159", 4 ), "3.1416" );
  1258. CHECK( HMath::round( "3.14159", 3 ), "3.142" );
  1259. CHECK( HMath::round( "3.14159", 2 ), "3.14" );
  1260. CHECK( HMath::round( "3.14159", 1 ), "3.1" );
  1261. CHECK( HMath::round( "3.14159", 0 ), "3" );
  1262. CHECK( HMath::round( "-2.6041980", 4 ), "-2.6042" );
  1263. CHECK( HMath::round( "-2.6041980", 3 ), "-2.604" );
  1264. CHECK( HMath::round( "-2.6041980", 2 ), "-2.6" );
  1265. CHECK( HMath::round( "-2.6041980", 1 ), "-2.6" );
  1266. CHECK( HMath::round( "-2.6041980", 0 ), "-3" );
  1267. CHECK( HMath::round( "NaN" ), "NaN" );
  1268. // integer
  1269. CHECK( HMath::integer( "0" ), "0" );
  1270. CHECK( HMath::integer( "0.25" ), "0" );
  1271. CHECK( HMath::integer( "0.85" ), "0" );
  1272. CHECK( HMath::integer( "14.0377" ), "14" );
  1273. CHECK( HMath::integer( "-0.25" ), "0" );
  1274. CHECK( HMath::integer( "-0.85" ), "0" );
  1275. CHECK( HMath::integer( "-14.0377" ), "-14" );
  1276. CHECK( HMath::integer( "NaN" ), "NaN" );
  1277. // frac
  1278. CHECK( HMath::frac( "0" ), "0" );
  1279. CHECK( HMath::frac( "3.14159" ), "0.14159" );
  1280. CHECK( HMath::frac( "0.14159" ), "0.14159" );
  1281. CHECK( HMath::frac( "-3.14159" ), "-0.14159" );
  1282. CHECK( HMath::frac( "-0.14159" ), "-0.14159" );
  1283. CHECK( HMath::frac( "NaN" ), "NaN" );
  1284. // checking function 'sqrt'
  1285. CHECK( HMath::sqrt(1), "1" );
  1286. CHECK( HMath::sqrt(4), "2" );
  1287. CHECK( HMath::sqrt(9), "3" );
  1288. CHECK( HMath::sqrt(16), "4" );
  1289. CHECK_PRECISE( HMath::sqrt(2), "1.41421356237309504880168872420969807856967187537695" );
  1290. CHECK_PRECISE( HMath::sqrt(3), "1.73205080756887729352744634150587236694280525381038" );
  1291. CHECK_PRECISE( HMath::sqrt(5), "2.23606797749978969640917366873127623544061835961153" );
  1292. CHECK_PRECISE( HMath::sqrt(7), "2.64575131106459059050161575363926042571025918308245" );
  1293. CHECK_PRECISE( HMath::sqrt(8), "2.82842712474619009760337744841939615713934375075390" );
  1294. CHECK_PRECISE( HMath::sqrt(10), "3.16227766016837933199889354443271853371955513932522" );
  1295. CHECK_PRECISE( HMath::sqrt(11), "3.31662479035539984911493273667068668392708854558935" );
  1296. CHECK_PRECISE( HMath::sqrt(12), "3.46410161513775458705489268301174473388561050762076" );
  1297. CHECK_PRECISE( HMath::sqrt(13), "3.60555127546398929311922126747049594625129657384525" );
  1298. CHECK_PRECISE( HMath::sqrt(14), "3.74165738677394138558374873231654930175601980777873" );
  1299. CHECK_PRECISE( HMath::sqrt(15), "3.87298334620741688517926539978239961083292170529159" );
  1300. CHECK_PRECISE( HMath::sqrt(17), "4.12310562561766054982140985597407702514719922537362" );
  1301. CHECK_PRECISE( HMath::sqrt(18), "4.24264068711928514640506617262909423570901562613084" );
  1302. CHECK_PRECISE( HMath::sqrt(19), "4.35889894354067355223698198385961565913700392523244" );
  1303. CHECK_PRECISE( HMath::sqrt(20), "4.47213595499957939281834733746255247088123671922305" );
  1304. CHECK( HMath::sqrt("0.04"), "0.2" );
  1305. CHECK( HMath::sqrt("0.09"), "0.3" );
  1306. CHECK( HMath::sqrt("0.16"), "0.4" );
  1307. CHECK( HMath::sqrt(-1), "NaN" );
  1308. CHECK( HMath::sqrt("NaN"), "NaN" );
  1309. // raise
  1310. CHECK( HMath::raise(10,-3), "0.001" );
  1311. CHECK( HMath::raise(10,-2), "0.01" );
  1312. CHECK( HMath::raise(10,-1), "0.1" );
  1313. CHECK( HMath::raise(10,0), "1" );
  1314. CHECK( HMath::raise(10,1), "10" );
  1315. CHECK( HMath::raise(10,2), "100" );
  1316. CHECK( HMath::raise(10,3), "1000" );
  1317. CHECK( HMath::raise(10,4), "10000" );
  1318. CHECK( HMath::raise("2","2"), "4" );
  1319. CHECK( HMath::raise("3","3"), "27" );
  1320. CHECK( HMath::raise("4","4"), "256" );
  1321. CHECK_PRECISE( HMath::raise("2","0.1"), "1.07177346253629316421300632502334202290638460497756" );
  1322. CHECK_PRECISE( HMath::raise("2","0.2"), "1.14869835499703500679862694677792758944385088909780" );
  1323. CHECK_PRECISE( HMath::raise("2","0.3"), "1.23114441334491628449939306916774310987613776110082" );
  1324. CHECK( HMath::raise("NaN","0"), "NaN" );
  1325. CHECK( HMath::raise("-1","NaN"), "NaN" );
  1326. // exp
  1327. CHECK_PRECISE( HMath::exp("0.1"), "1.10517091807564762481170782649024666822454719473752" );
  1328. CHECK_PRECISE( HMath::exp("0.2"), "1.22140275816016983392107199463967417030758094152050" );
  1329. CHECK_PRECISE( HMath::exp("0.3"), "1.34985880757600310398374431332800733037829969735937" );
  1330. CHECK_PRECISE( HMath::exp("0.4"), "1.49182469764127031782485295283722228064328277393743" );
  1331. CHECK_PRECISE( HMath::exp("0.5"), "1.64872127070012814684865078781416357165377610071015" );
  1332. CHECK_PRECISE( HMath::exp("0.6"), "1.82211880039050897487536766816286451338223880854644" );
  1333. CHECK_PRECISE( HMath::exp("0.7"), "2.01375270747047652162454938858306527001754239414587" );
  1334. CHECK_PRECISE( HMath::exp("0.8"), "2.22554092849246760457953753139507675705363413504848" );
  1335. CHECK_PRECISE( HMath::exp("0.9"), "2.45960311115694966380012656360247069542177230644008" );
  1336. CHECK_PRECISE( HMath::exp("1.0"), "2.71828182845904523536028747135266249775724709369996" );
  1337. // ln
  1338. CHECK_PRECISE( HMath::ln("0.1"), "-2.30258509299404568401799145468436420760110148862877" );
  1339. CHECK_PRECISE( HMath::ln("0.2"), "-1.60943791243410037460075933322618763952560135426852" );
  1340. CHECK_PRECISE( HMath::ln("0.3"), "-1.20397280432593599262274621776183850295361093080602" );
  1341. CHECK_PRECISE( HMath::ln("0.4"), "-0.91629073187415506518352721176801107145010121990826" );
  1342. CHECK_PRECISE( HMath::ln("0.5"), "-0.69314718055994530941723212145817656807550013436026" );
  1343. CHECK_PRECISE( HMath::ln("0.6"), "-0.51082562376599068320551409630366193487811079644577" );
  1344. CHECK_PRECISE( HMath::ln("0.7"), "-0.35667494393873237891263871124118447796401675904691" );
  1345. CHECK_PRECISE( HMath::ln("0.8"), "-0.22314355131420975576629509030983450337460108554801" );
  1346. CHECK_PRECISE( HMath::ln("0.9"), "-0.10536051565782630122750098083931279830612037298327" );
  1347. CHECK_PRECISE( HMath::ln("1.0"), "0.00000000000000000000000000000000000000000000000000" );
  1348. CHECK_PRECISE( HMath::ln("1.1"), "0.09531017980432486004395212328076509222060536530864" );
  1349. CHECK_PRECISE( HMath::ln("1.2"), "0.18232155679395462621171802515451463319738933791449" );
  1350. CHECK_PRECISE( HMath::ln("1.3"), "0.26236426446749105203549598688095439720416645613143" );
  1351. CHECK_PRECISE( HMath::ln("1.4"), "0.33647223662121293050459341021699209011148337531334" );
  1352. CHECK_PRECISE( HMath::ln("1.5"), "0.40546510810816438197801311546434913657199042346249" );
  1353. CHECK_PRECISE( HMath::ln("1.6"), "0.47000362924573555365093703114834206470089904881225" );
  1354. CHECK_PRECISE( HMath::ln("1.7"), "0.53062825106217039623154316318876232798710152395697" );
  1355. CHECK_PRECISE( HMath::ln("1.8"), "0.58778666490211900818973114061886376976937976137698" );
  1356. CHECK_PRECISE( HMath::ln("1.9"), "0.64185388617239477599103597720348932963627777267036" );
  1357. CHECK_PRECISE( HMath::ln("2.0"), "0.69314718055994530941723212145817656807550013436026" );
  1358. CHECK_PRECISE( HMath::ln("3.0"), "1.09861228866810969139524523692252570464749055782275" );
  1359. CHECK_PRECISE( HMath::ln("4.0"), "1.38629436111989061883446424291635313615100026872051" );
  1360. CHECK_PRECISE( HMath::ln("100"), "4.60517018598809136803598290936872841520220297725755" );
  1361. // log
  1362. CHECK( HMath::log("1e-5"), "-5" );
  1363. CHECK( HMath::log("1e-4"), "-4" );
  1364. CHECK( HMath::log("1e-3"), "-3" );
  1365. CHECK( HMath::log("10"), "1" );
  1366. CHECK( HMath::log("100"), "2" );
  1367. CHECK( HMath::log("1000"), "3" );
  1368. CHECK( HMath::log("10000"), "4" );
  1369. CHECK( HMath::log("1e5"), "5" );
  1370. CHECK( HMath::log("1e6"), "6" );
  1371. CHECK( HMath::log("1e7"), "7" );
  1372. CHECK( HMath::log("1e8"), "8" );
  1373. CHECK( HMath::log("1e9"), "9" );
  1374. CHECK( HMath::log("1e10"), "10" );
  1375. CHECK( HMath::log("-1"), "NaN" );
  1376. CHECK( HMath::log("NaN"), "NaN" );
  1377. // sin
  1378. CHECK( HMath::sin( "0" ), "0" );
  1379. CHECK( HMath::sin( HMath::pi()/4 ), "0.7071067811865475244" );
  1380. CHECK( HMath::sin( HMath::pi()/3 ), "0.86602540378443864676");
  1381. CHECK( HMath::sin( HMath::pi()/2 ), "1" );
  1382. CHECK( HMath::sin( HMath::pi()/1 ), "0" );
  1383. CHECK( HMath::sin( HMath::pi()*2/3 ), "0.86602540378443864676");
  1384. CHECK( HMath::sin( HMath::pi()*4/3 ), "-0.86602540378443864676");
  1385. CHECK( HMath::sin( HMath::pi()*5/3 ), "-0.86602540378443864676");
  1386. CHECK( HMath::sin( HMath::pi()*6/3 ), "0");
  1387. CHECK( HMath::sin( HMath::pi()*7/3 ), "0.86602540378443864676");
  1388. CHECK( HMath::sin( HMath::pi()*9/3 ), "0");
  1389. CHECK_PRECISE( HMath::sin("0.0"), "0.00000000000000000000000000000000000000000000000000" );
  1390. CHECK_PRECISE( HMath::sin("0.1"), "0.09983341664682815230681419841062202698991538801798" );
  1391. CHECK_PRECISE( HMath::sin("0.2"), "0.19866933079506121545941262711838975037020672954021" );
  1392. CHECK_PRECISE( HMath::sin("0.3"), "0.29552020666133957510532074568502737367783211174262" );
  1393. CHECK_PRECISE( HMath::sin("0.4"), "0.38941834230865049166631175679570526459306018344396" );
  1394. CHECK_PRECISE( HMath::sin("0.5"), "0.47942553860420300027328793521557138808180336794060" );
  1395. CHECK_PRECISE( HMath::sin("0.6"), "0.56464247339503535720094544565865790710988808499415" );
  1396. CHECK_PRECISE( HMath::sin("0.7"), "0.64421768723769105367261435139872018306581384457369" );
  1397. CHECK_PRECISE( HMath::sin("0.8"), "0.71735609089952276162717461058138536619278523779142" );
  1398. CHECK_PRECISE( HMath::sin("0.9"), "0.78332690962748338846138231571354862314014792572031" );
  1399. CHECK_PRECISE( HMath::sin("1.0"), "0.84147098480789650665250232163029899962256306079837" );
  1400. CHECK_PRECISE( HMath::sin("2.0"), "0.90929742682568169539601986591174484270225497144789" );
  1401. CHECK_PRECISE( HMath::sin("3.0"), "0.14112000805986722210074480280811027984693326425227" );
  1402. CHECK_PRECISE( HMath::sin("4.0"), "-0.75680249530792825137263909451182909413591288733647" );
  1403. CHECK_PRECISE( HMath::sin("5.0"), "-0.95892427466313846889315440615599397335246154396460" );
  1404. // cos
  1405. CHECK( HMath::cos( "0" ), "1" );
  1406. CHECK( HMath::cos( HMath::pi()/4 ), "0.7071067811865475244" );
  1407. CHECK( HMath::cos( HMath::pi()/3 ), "0.5");
  1408. CHECK( HMath::cos( HMath::pi()/2 ), "0" );
  1409. CHECK( HMath::cos( HMath::pi()/1 ), "-1" );
  1410. CHECK( HMath::cos( HMath::pi()*2/3 ), "-0.5");
  1411. CHECK( HMath::cos( HMath::pi()*4/3 ), "-0.5");
  1412. CHECK( HMath::cos( HMath::pi()*5/3 ), "0.5");
  1413. CHECK( HMath::cos( HMath::pi()*6/3 ), "1");
  1414. CHECK( HMath::cos( HMath::pi()*7/3 ), "0.5");
  1415. CHECK( HMath::cos( HMath::pi()*9/3 ), "-1");
  1416. CHECK_PRECISE( HMath::cos("0.0"), "1.00000000000000000000000000000000000000000000000000" );
  1417. CHECK_PRECISE( HMath::cos("0.1"), "0.99500416527802576609556198780387029483857622541508" );
  1418. CHECK_PRECISE( HMath::cos("0.2"), "0.98006657784124163112419651674816887739352436080657" );
  1419. CHECK_PRECISE( HMath::cos("0.3"), "0.95533648912560601964231022756804989824421408263204" );
  1420. CHECK_PRECISE( HMath::cos("0.4"), "0.92106099400288508279852673205180161402585956931985" );
  1421. CHECK_PRECISE( HMath::cos("0.5"), "0.87758256189037271611628158260382965199164519710974" );
  1422. CHECK_PRECISE( HMath::cos("0.6"), "0.82533561490967829724095249895537603887809103918847" );
  1423. CHECK_PRECISE( HMath::cos("0.7"), "0.76484218728448842625585999019186490926821055037370" );
  1424. CHECK_PRECISE( HMath::cos("0.8"), "0.69670670934716542092074998164232492610178601370806" );
  1425. CHECK_PRECISE( HMath::cos("0.9"), "0.62160996827066445648471615140713350872176136659124" );
  1426. CHECK_PRECISE( HMath::cos("1.0"), "0.54030230586813971740093660744297660373231042061792" );
  1427. CHECK_PRECISE( HMath::cos("2.0"), "-0.41614683654714238699756822950076218976600077107554" );
  1428. CHECK_PRECISE( HMath::cos("3.0"), "-0.98999249660044545727157279473126130239367909661559" );
  1429. CHECK_PRECISE( HMath::cos("4.0"), "-0.65364362086361191463916818309775038142413359664622" );
  1430. // tan
  1431. CHECK( HMath::tan( HMath::pi()/4 ), "1" );
  1432. CHECK( HMath::tan( HMath::pi()/3 ), "1.73205080756887729353");
  1433. CHECK( HMath::tan( HMath::pi()/1 ), "0" );
  1434. CHECK_PRECISE( HMath::tan("0.0"), "0.00000000000000000000000000000000000000000000000000" );
  1435. CHECK_PRECISE( HMath::tan("0.1"), "0.10033467208545054505808004578111153681900480457644" );
  1436. CHECK_PRECISE( HMath::tan("0.2"), "0.20271003550867248332135827164753448262687566965163" );
  1437. CHECK_PRECISE( HMath::tan("0.3"), "0.30933624960962323303530367969829466725781590680046" );
  1438. CHECK_PRECISE( HMath::tan("0.4"), "0.42279321873816176198163542716529033394198977271569" );
  1439. CHECK_PRECISE( HMath::tan("0.5"), "0.54630248984379051325517946578028538329755172017979" );
  1440. CHECK_PRECISE( HMath::tan("0.6"), "0.68413680834169231707092541746333574524265408075678" );
  1441. CHECK_PRECISE( HMath::tan("0.7"), "0.84228838046307944812813500221293771718722125080420" );
  1442. CHECK_PRECISE( HMath::tan("0.8"), "1.02963855705036401274636117282036528416821960677231" );
  1443. CHECK_PRECISE( HMath::tan("0.9"), "1.26015821755033913713457548539574847783362583439629" );
  1444. CHECK_PRECISE( HMath::tan("1.0"), "1.55740772465490223050697480745836017308725077238152" );
  1445. CHECK_PRECISE( HMath::tan("2.0"), "-2.18503986326151899164330610231368254343201774622766" );
  1446. CHECK_PRECISE( HMath::tan("3.0"), "-0.14254654307427780529563541053391349322609228490180" );
  1447. CHECK_PRECISE( HMath::tan("4.0"), "1.15782128234957758313734241826732392311976276736714" );
  1448. // atan
  1449. CHECK_PRECISE( HMath::atan("0.0"), "0.00000000000000000000000000000000000000000000000000" );
  1450. CHECK_PRECISE( HMath::atan("0.1"), "0.09966865249116202737844611987802059024327832250431" );
  1451. CHECK_PRECISE( HMath::atan("0.2"), "0.19739555984988075837004976519479029344758510378785" );
  1452. CHECK_PRECISE( HMath::atan("0.3"), "0.29145679447786709199560462143289119350316759901207" );
  1453. CHECK_PRECISE( HMath::atan("0.4"), "0.38050637711236488630358791681043310449740571365810" );
  1454. CHECK_PRECISE( HMath::atan("0.5"), "0.46364760900080611621425623146121440202853705428612" );
  1455. CHECK_PRECISE( HMath::atan("0.6"), "0.54041950027058415544357836460859991013514825146259" );
  1456. CHECK_PRECISE( HMath::atan("1.0"), "0.78539816339744830961566084581987572104929234984378" );
  1457. CHECK_PRECISE( HMath::atan("-0.1"), "-0.09966865249116202737844611987802059024327832250431" );
  1458. CHECK_PRECISE( HMath::atan("-0.2"), "-0.19739555984988075837004976519479029344758510378785" );
  1459. CHECK_PRECISE( HMath::atan("-0.3"), "-0.29145679447786709199560462143289119350316759901207" );
  1460. CHECK_PRECISE( HMath::atan("-0.4"), "-0.38050637711236488630358791681043310449740571365810" );
  1461. CHECK_PRECISE( HMath::atan("-0.5"), "-0.46364760900080611621425623146121440202853705428612" );
  1462. CHECK_PRECISE( HMath::atan("-0.6"), "-0.54041950027058415544357836460859991013514825146259" );
  1463. CHECK_PRECISE( HMath::atan("-1.0"), "-0.78539816339744830961566084581987572104929234984378" );
  1464. // asin
  1465. CHECK_PRECISE( HMath::asin("0.0"), "0.00000000000000000000000000000000000000000000000000" );
  1466. CHECK_PRECISE( HMath::asin("0.1"), "0.10016742116155979634552317945269331856867597222963" );
  1467. CHECK_PRECISE( HMath::asin("0.2"), "0.20135792079033079145512555221762341024003808140223" );
  1468. CHECK_PRECISE( HMath::asin("0.3"), "0.30469265401539750797200296122752916695456003170678" );
  1469. CHECK_PRECISE( HMath::asin("0.4"), "0.41151684606748801938473789761733560485570113512703" );
  1470. // acos
  1471. CHECK_PRECISE( HMath::acos("0.1"), "1.47062890563333682288579851218705812352990872745792" );
  1472. CHECK_PRECISE( HMath::acos("0.2"), "1.36943840600456582777619613942212803185854661828532" );
  1473. CHECK_PRECISE( HMath::acos("0.3"), "1.26610367277949911125931873041222227514402466798078" );
  1474. CHECK_PRECISE( HMath::acos("0.4"), "1.15927948072740859984658379402241583724288356456053" );
  1475. // consistency: tan vs atan
  1476. CHECK( HMath::atan("0.10033467208545054505808004578111153681900480457644"), "0.1" );
  1477. CHECK( HMath::atan("0.20271003550867248332135827164753448262687566965163"), "0.2" );
  1478. CHECK( HMath::atan("0.30933624960962323303530367969829466725781590680046"), "0.3" );
  1479. CHECK( HMath::atan("0.42279321873816176198163542716529033394198977271569"), "0.4" );
  1480. CHECK( HMath::atan("0.54630248984379051325517946578028538329755172017979"), "0.5" );
  1481. CHECK( HMath::atan("0.68413680834169231707092541746333574524265408075678"), "0.6" );
  1482. CHECK( HMath::atan("0.84228838046307944812813500221293771718722125080420"), "0.7" );
  1483. CHECK( HMath::atan("1.02963855705036401274636117282036528416821960677231"), "0.8" );
  1484. CHECK( HMath::atan("1.26015821755033913713457548539574847783362583439629"), "0.9" );
  1485. CHECK( HMath::atan("1.55740772465490223050697480745836017308725077238152"), "1" );
  1486. // consistency: sin vs asin for small angle
  1487. CHECK( HMath::asin("0.09983341664682815230681419841062202698991538801798" ), "0.1");
  1488. CHECK( HMath::asin("0.19866933079506121545941262711838975037020672954021" ), "0.2");
  1489. CHECK( HMath::asin("0.29552020666133957510532074568502737367783211174262" ), "0.3");
  1490. CHECK( HMath::asin("0.38941834230865049166631175679570526459306018344396" ), "0.4");
  1491. CHECK( HMath::asin("0.47942553860420300027328793521557138808180336794060" ), "0.5");
  1492. CHECK( HMath::asin("0.56464247339503535720094544565865790710988808499415" ), "0.6");
  1493. CHECK( HMath::asin("0.64421768723769105367261435139872018306581384457369" ), "0.7");
  1494. CHECK( HMath::asin("0.71735609089952276162717461058138536619278523779142" ), "0.8");
  1495. // sinh
  1496. CHECK_PRECISE( HMath::sinh("0.1"), "0.10016675001984402582372938352190502351492091687856" );
  1497. CHECK_PRECISE( HMath::sinh("0.2"), "0.20133600254109398762556824301031737297449484262574" );
  1498. CHECK_PRECISE( HMath::sinh("0.3"), "0.30452029344714261895843526700509522909802423268018" );
  1499. CHECK_PRECISE( HMath::sinh("0.4"), "0.41075232580281550854021001384469810435315092436331" );
  1500. CHECK_PRECISE( HMath::sinh("0.5"), "0.52109530549374736162242562641149155910592898261148" );
  1501. CHECK_PRECISE( HMath::sinh("0.6"), "0.63665358214824127112345437546514831902496342592790" );
  1502. CHECK_PRECISE( HMath::sinh("0.7"), "0.75858370183953350345987464759276815415493761421703" );
  1503. CHECK_PRECISE( HMath::sinh("0.8"), "0.88810598218762300657471757318975698055970959688815" );
  1504. CHECK_PRECISE( HMath::sinh("0.9"), "1.02651672570817527595833616197842235379403446513485" );
  1505. CHECK_PRECISE( HMath::sinh("1.0"), "1.17520119364380145688238185059560081515571798133410" );
  1506. // cosh
  1507. CHECK_PRECISE( HMath::cosh("0.1"), "1.00500416805580359898797844296834164470962627785896" );
  1508. CHECK_PRECISE( HMath::cosh("0.2"), "1.02006675561907584629550375162935679733308609889476" );
  1509. CHECK_PRECISE( HMath::cosh("0.3"), "1.04533851412886048502530904632291210128027546467919" );
  1510. CHECK_PRECISE( HMath::cosh("0.4"), "1.08107237183845480928464293899252417629013184957412" );
  1511. CHECK_PRECISE( HMath::cosh("0.5"), "1.12762596520638078522622516140267201254784711809867" );
  1512. CHECK_PRECISE( HMath::cosh("0.6"), "1.18546521824226770375191329269771619435727538261853" );
  1513. CHECK_PRECISE( HMath::cosh("0.7"), "1.25516900563094301816467474099029711586260477992884" );
  1514. CHECK_PRECISE( HMath::cosh("0.8"), "1.33743494630484459800481995820531977649392453816033" );
  1515. CHECK_PRECISE( HMath::cosh("0.9"), "1.43308638544877438784179040162404834162773784130523" );
  1516. CHECK_PRECISE( HMath::cosh("1.0"), "1.54308063481524377847790562075706168260152911236586" );
  1517. }
  1518. int test_hmath()
  1519. {
  1520. hmath_total_tests = 0;
  1521. hmath_failed_tests = 0;
  1522. test_create();
  1523. test_format();
  1524. test_op();
  1525. test_functions();
  1526. std::cout << hmath_total_tests << " total, ";
  1527. std::cout << hmath_failed_tests << " failed\n";
  1528. HMath::finalize();
  1529. return hmath_failed_tests;
  1530. };
  1531. #endif
  1532. // vim: set et sw=2 ts=8: