PageRenderTime 37ms CodeModel.GetById 8ms RepoModel.GetById 0ms app.codeStats 0ms

/d/phobos/std/math2.d

https://bitbucket.org/goshawk/gdc/
D | 954 lines | 598 code | 124 blank | 232 comment | 117 complexity | a82235be2d1190d3d73019a7693217ca MD5 | raw file
Possible License(s): GPL-2.0, AGPL-1.0
  1. /* This module is obsolete and will be removed eventually */
  2. /*
  3. * Copyright (c) 2002
  4. * Pavel "EvilOne" Minayev
  5. *
  6. * Permission to use, copy, modify, distribute and sell this software
  7. * and its documentation for any purpose is hereby granted without fee,
  8. * provided that the above copyright notice appear in all copies and
  9. * that both that copyright notice and this permission notice appear
  10. * in supporting documentation. Author makes no representations about
  11. * the suitability of this software for any purpose. It is provided
  12. * "as is" without express or implied warranty.
  13. * Source: $(PHOBOSSRC std/_math2.d)
  14. */
  15. /* NOTE: This file has been patched from the original DMD distribution to
  16. work with the GDC compiler.
  17. Modified by David Friedman, September 2007
  18. */
  19. module std.math2;
  20. private import std.math, std.string, std.c.stdlib, std.c.stdio;
  21. version(GNU)
  22. static import std.c.math;
  23. //debug=math2;
  24. /****************************************
  25. * compare floats with given precision
  26. */
  27. bool feq(real a, real b)
  28. {
  29. return feq(a, b, 0.000001);
  30. }
  31. bool feq(real a, real b, real eps)
  32. {
  33. return abs(a - b) <= eps;
  34. }
  35. /*********************************
  36. * Modulus
  37. */
  38. int abs(int n)
  39. {
  40. return n > 0 ? n : -n;
  41. }
  42. long abs(long n)
  43. {
  44. return n > 0 ? n : -n;
  45. }
  46. real abs(real n)
  47. {
  48. // just let the compiler handle it
  49. return std.math.fabs(n);
  50. }
  51. /*********************************
  52. * Square
  53. */
  54. int sqr(int n)
  55. {
  56. return n * n;
  57. }
  58. long sqr(long n)
  59. {
  60. return n * n;
  61. }
  62. real sqr(real n)
  63. {
  64. return n * n;
  65. }
  66. unittest
  67. {
  68. assert(sqr(sqr(3)) == 81);
  69. }
  70. private ushort fp_cw_chop = 7999;
  71. /*********************************
  72. * Integer part
  73. */
  74. real trunc(real n)
  75. {
  76. version (GNU_Need_trunc) {
  77. return n >= 0 ? std.math.floor(n) : std.math.ceil(n);
  78. } else version (GNU) {
  79. return std.c.math.truncl(n);
  80. } else {
  81. ushort cw;
  82. asm
  83. {
  84. fstcw cw;
  85. fldcw fp_cw_chop;
  86. fld n;
  87. frndint;
  88. fldcw cw;
  89. }
  90. }
  91. }
  92. unittest
  93. {
  94. assert(feq(trunc(+123.456), +123.0L));
  95. assert(feq(trunc(-123.456), -123.0L));
  96. }
  97. /*********************************
  98. * Fractional part
  99. */
  100. real frac(real n)
  101. {
  102. return n - trunc(n);
  103. }
  104. unittest
  105. {
  106. assert(feq(frac(+123.456), +0.456L));
  107. assert(feq(frac(-123.456), -0.456L));
  108. }
  109. /*********************************
  110. * Sign
  111. */
  112. int sign(int n)
  113. {
  114. return (n > 0 ? +1 : (n < 0 ? -1 : 0));
  115. }
  116. unittest
  117. {
  118. assert(sign(0) == 0);
  119. assert(sign(+666) == +1);
  120. assert(sign(-666) == -1);
  121. }
  122. int sign(long n)
  123. {
  124. return (n > 0 ? +1 : (n < 0 ? -1 : 0));
  125. }
  126. unittest
  127. {
  128. assert(sign(0) == 0);
  129. assert(sign(+666L) == +1);
  130. assert(sign(-666L) == -1);
  131. }
  132. int sign(real n)
  133. {
  134. return (n > 0 ? +1 : (n < 0 ? -1 : 0));
  135. }
  136. unittest
  137. {
  138. assert(sign(0.0L) == 0);
  139. assert(sign(+123.456L) == +1);
  140. assert(sign(-123.456L) == -1);
  141. }
  142. /**********************************************************
  143. * Cycles <-> radians <-> grads <-> degrees conversions
  144. */
  145. real cycle2deg(real c)
  146. {
  147. return c * 360;
  148. }
  149. real cycle2rad(real c)
  150. {
  151. return c * PI * 2;
  152. }
  153. real cycle2grad(real c)
  154. {
  155. return c * 400;
  156. }
  157. real deg2cycle(real d)
  158. {
  159. return d / 360;
  160. }
  161. real deg2rad(real d)
  162. {
  163. return d / 180 * PI;
  164. }
  165. real deg2grad(real d)
  166. {
  167. return d / 90 * 100;
  168. }
  169. real rad2deg(real r)
  170. {
  171. return r / PI * 180;
  172. }
  173. real rad2cycle(real r)
  174. {
  175. return r / (PI * 2);
  176. }
  177. real rad2grad(real r)
  178. {
  179. return r / PI * 200;
  180. }
  181. real grad2deg(real g)
  182. {
  183. return g / 100 * 90;
  184. }
  185. real grad2cycle(real g)
  186. {
  187. return g / 400;
  188. }
  189. real grad2rad(real g)
  190. {
  191. return g / 200 * PI;
  192. }
  193. unittest
  194. {
  195. assert(feq(cycle2deg(0.5), 180));
  196. assert(feq(cycle2rad(0.5), PI));
  197. assert(feq(cycle2grad(0.5), 200));
  198. assert(feq(deg2cycle(180), 0.5));
  199. assert(feq(deg2rad(180), PI));
  200. assert(feq(deg2grad(180), 200));
  201. assert(feq(rad2deg(PI), 180));
  202. assert(feq(rad2cycle(PI), 0.5));
  203. assert(feq(rad2grad(PI), 200));
  204. assert(feq(grad2deg(200), 180));
  205. assert(feq(grad2cycle(200), 0.5));
  206. assert(feq(grad2rad(200), PI));
  207. }
  208. /************************************
  209. * Arithmetic average of values
  210. */
  211. real avg(real[] n)
  212. {
  213. real result = 0;
  214. for (size_t i = 0; i < n.length; i++)
  215. result += n[i];
  216. return result / n.length;
  217. }
  218. unittest
  219. {
  220. static real[4] n = [ 1, 2, 4, 5 ];
  221. assert(feq(avg(n), 3));
  222. }
  223. /*************************************
  224. * Sum of values
  225. */
  226. int sum(int[] n)
  227. {
  228. long result = 0;
  229. for (size_t i = 0; i < n.length; i++)
  230. result += n[i];
  231. return cast(int)result;
  232. }
  233. unittest
  234. {
  235. static int[3] n = [ 1, 2, 3 ];
  236. assert(sum(n) == 6);
  237. }
  238. long sum(long[] n)
  239. {
  240. long result = 0;
  241. for (size_t i = 0; i < n.length; i++)
  242. result += n[i];
  243. return result;
  244. }
  245. unittest
  246. {
  247. static long[3] n = [ 1, 2, 3 ];
  248. assert(sum(n) == 6);
  249. }
  250. real sum(real[] n)
  251. {
  252. real result = 0;
  253. for (size_t i = 0; i < n.length; i++)
  254. result += n[i];
  255. return result;
  256. }
  257. unittest
  258. {
  259. static real[3] n = [ 1, 2, 3 ];
  260. assert(feq(sum(n), 6));
  261. }
  262. /*************************************
  263. * The smallest value
  264. */
  265. int min(int[] n)
  266. {
  267. int result = int.max;
  268. for (size_t i = 0; i < n.length; i++)
  269. if (n[i] < result)
  270. result = n[i];
  271. return result;
  272. }
  273. unittest
  274. {
  275. static int[3] n = [ 2, -1, 0 ];
  276. assert(min(n) == -1);
  277. }
  278. long min(long[] n)
  279. {
  280. long result = long.max;
  281. for (size_t i = 0; i < n.length; i++)
  282. if (n[i] < result)
  283. result = n[i];
  284. return result;
  285. }
  286. unittest
  287. {
  288. static long[3] n = [ 2, -1, 0 ];
  289. assert(min(n) == -1);
  290. }
  291. real min(real[] n)
  292. {
  293. real result = real.max;
  294. for (size_t i = 0; i < n.length; i++)
  295. {
  296. if (n[i] < result)
  297. result = n[i];
  298. }
  299. return result;
  300. }
  301. unittest
  302. {
  303. static real[3] n = [ 2.0, -1.0, 0.0 ];
  304. assert(feq(min(n), -1));
  305. }
  306. int min(int a, int b)
  307. {
  308. return a < b ? a : b;
  309. }
  310. unittest
  311. {
  312. assert(min(1, 2) == 1);
  313. }
  314. long min(long a, long b)
  315. {
  316. return a < b ? a : b;
  317. }
  318. unittest
  319. {
  320. assert(min(1L, 2L) == 1);
  321. }
  322. real min(real a, real b)
  323. {
  324. return a < b ? a : b;
  325. }
  326. unittest
  327. {
  328. assert(feq(min(1.0L, 2.0L), 1.0L));
  329. }
  330. /*************************************
  331. * The largest value
  332. */
  333. int max(int[] n)
  334. {
  335. int result = int.min;
  336. for (size_t i = 0; i < n.length; i++)
  337. if (n[i] > result)
  338. result = n[i];
  339. return result;
  340. }
  341. unittest
  342. {
  343. static int[3] n = [ 0, 2, -1 ];
  344. assert(max(n) == 2);
  345. }
  346. long max(long[] n)
  347. {
  348. long result = long.min;
  349. for (size_t i = 0; i < n.length; i++)
  350. if (n[i] > result)
  351. result = n[i];
  352. return result;
  353. }
  354. unittest
  355. {
  356. static long[3] n = [ 0, 2, -1 ];
  357. assert(max(n) == 2);
  358. }
  359. real max(real[] n)
  360. {
  361. real result = real.min;
  362. for (size_t i = 0; i < n.length; i++)
  363. if (n[i] > result)
  364. result = n[i];
  365. return result;
  366. }
  367. unittest
  368. {
  369. static real[3] n = [ 0.0, 2.0, -1.0 ];
  370. assert(feq(max(n), 2));
  371. }
  372. int max(int a, int b)
  373. {
  374. return a > b ? a : b;
  375. }
  376. unittest
  377. {
  378. assert(max(1, 2) == 2);
  379. }
  380. long max(long a, long b)
  381. {
  382. return a > b ? a : b;
  383. }
  384. unittest
  385. {
  386. assert(max(1L, 2L) == 2);
  387. }
  388. real max(real a, real b)
  389. {
  390. return a > b ? a : b;
  391. }
  392. unittest
  393. {
  394. assert(feq(max(1.0L, 2.0L), 2.0L));
  395. }
  396. /*************************************
  397. * Arccotangent
  398. */
  399. real acot(real x)
  400. {
  401. return std.math.tan(1.0 / x);
  402. }
  403. unittest
  404. {
  405. assert(feq(acot(cot(0.000001)), 0.000001));
  406. }
  407. /*************************************
  408. * Arcsecant
  409. */
  410. real asec(real x)
  411. {
  412. return std.math.cos(1.0 / x);
  413. }
  414. /*************************************
  415. * Arccosecant
  416. */
  417. real acosec(real x)
  418. {
  419. return std.math.sin(1.0 / x);
  420. }
  421. /*************************************
  422. * Tangent
  423. */
  424. /+
  425. real tan(real x)
  426. {
  427. asm
  428. {
  429. fld x;
  430. fptan;
  431. fstp ST(0);
  432. fwait;
  433. }
  434. }
  435. unittest
  436. {
  437. assert(feq(tan(PI / 3), std.math.sqrt(3)));
  438. }
  439. +/
  440. /*************************************
  441. * Cotangent
  442. */
  443. real cot(real x)
  444. {
  445. version(GNU) {
  446. // %% is the asm below missing fld1?
  447. return 1/std.c.math.tanl(x);
  448. } else {
  449. asm
  450. {
  451. fld x;
  452. fptan;
  453. fdivrp;
  454. fwait;
  455. }
  456. }
  457. }
  458. unittest
  459. {
  460. assert(feq(cot(PI / 6), std.math.sqrt(3.0L)));
  461. }
  462. /*************************************
  463. * Secant
  464. */
  465. real sec(real x)
  466. {
  467. version(GNU) {
  468. return 1/std.c.math.cosl(x);
  469. } else {
  470. asm
  471. {
  472. fld x;
  473. fcos;
  474. fld1;
  475. fdivrp;
  476. fwait;
  477. }
  478. }
  479. }
  480. /*************************************
  481. * Cosecant
  482. */
  483. real cosec(real x)
  484. {
  485. version(GNU) {
  486. // %% is the asm below missing fld1?
  487. return 1/std.c.math.sinl(x);
  488. } else {
  489. asm
  490. {
  491. fld x;
  492. fsin;
  493. fld1;
  494. fdivrp;
  495. fwait;
  496. }
  497. }
  498. }
  499. /*********************************************
  500. * Extract mantissa and exponent from float
  501. */
  502. /+
  503. real frexp(real x, out int exponent)
  504. {
  505. version (GNU) {
  506. return std.c.math.frexpl(x, & exponent);
  507. } else {
  508. asm
  509. {
  510. fld x;
  511. mov EDX, exponent;
  512. mov dword ptr [EDX], 0;
  513. ftst;
  514. fstsw AX;
  515. fwait;
  516. sahf;
  517. jz done;
  518. fxtract;
  519. fxch;
  520. fistp dword ptr [EDX];
  521. fld1;
  522. fchs;
  523. fxch;
  524. fscale;
  525. inc dword ptr [EDX];
  526. fstp ST(1);
  527. done:
  528. fwait;
  529. }
  530. }
  531. }
  532. unittest
  533. {
  534. int exponent;
  535. real mantissa = frexp(123.456, exponent);
  536. assert(feq(mantissa * std.math.pow(2.0L, cast(real)exponent), 123.456));
  537. }
  538. +/
  539. /*************************************
  540. * Hyperbolic cotangent
  541. */
  542. real coth(real x)
  543. {
  544. return 1 / std.math.tanh(x);
  545. }
  546. unittest
  547. {
  548. real r1 = coth(1);
  549. real r2 = std.math.sinh(1);
  550. real r3 = std.math.tanh(1);
  551. real r4 = coth(1);
  552. printf("%0.5Lg %0.5Lg %0.5Lg %0.5Lg\n", r1, r2, r3, r4);
  553. printf("%0.5g %0.5g %0.5g %0.5g\n",
  554. coth(1), std.math.sinh(1), std.math.tanh(1), coth(1));
  555. assert(feq(coth(1), std.math.cosh(1) / std.math.sinh(1)));
  556. }
  557. /*************************************
  558. * Hyperbolic secant
  559. */
  560. real sech(real x)
  561. {
  562. return 1 / std.math.cosh(x);
  563. }
  564. /*************************************
  565. * Hyperbolic cosecant
  566. */
  567. real cosech(real x)
  568. {
  569. return 1 / std.math.sinh(x);
  570. }
  571. /*************************************
  572. * Hyperbolic arccosine
  573. */
  574. /+
  575. real acosh(real x)
  576. {
  577. if (x <= 1)
  578. return 0;
  579. else if (x > 1.0e10)
  580. return log(2) + log(x);
  581. else
  582. return log(x + std.math.sqrt((x - 1) * (x + 1)));
  583. }
  584. unittest
  585. {
  586. assert(acosh(0.5) == 0);
  587. assert(feq(acosh(std.math.cosh(3)), 3));
  588. }
  589. +/
  590. /*************************************
  591. * Hyperbolic arcsine
  592. */
  593. /+
  594. real asinh(real x)
  595. {
  596. if (!x)
  597. return 0;
  598. else if (x > 1.0e10)
  599. return log(2) + log(1.0e10);
  600. else if (x < -1.0e10)
  601. return -log(2) - log(1.0e10);
  602. else
  603. {
  604. real z = x * x;
  605. return x > 0 ?
  606. std.math.log1p(x + z / (1.0 + std.math.sqrt(1.0 + z))) :
  607. -std.math.log1p(-x + z / (1.0 + std.math.sqrt(1.0 + z)));
  608. }
  609. }
  610. unittest
  611. {
  612. assert(asinh(0) == 0);
  613. assert(feq(asinh(std.math.sinh(3)), 3));
  614. }
  615. +/
  616. /*************************************
  617. * Hyperbolic arctangent
  618. */
  619. /+
  620. real atanh(real x)
  621. {
  622. if (!x)
  623. return 0;
  624. else
  625. {
  626. if (x >= 1)
  627. return real.max;
  628. else if (x <= -1)
  629. return -real.max;
  630. else
  631. return x > 0 ?
  632. 0.5 * std.math.log1p((2.0 * x) / (1.0 - x)) :
  633. -0.5 * std.math.log1p((-2.0 * x) / (1.0 + x));
  634. }
  635. }
  636. unittest
  637. {
  638. assert(atanh(0) == 0);
  639. assert(feq(atanh(std.math.tanh(0.5)), 0.5));
  640. }
  641. +/
  642. /*************************************
  643. * Hyperbolic arccotangent
  644. */
  645. real acoth(real x)
  646. {
  647. return 1 / acot(x);
  648. }
  649. unittest
  650. {
  651. assert(feq(acoth(coth(0.01)), 100));
  652. }
  653. /*************************************
  654. * Hyperbolic arcsecant
  655. */
  656. real asech(real x)
  657. {
  658. return 1 / asec(x);
  659. }
  660. /*************************************
  661. * Hyperbolic arccosecant
  662. */
  663. real acosech(real x)
  664. {
  665. return 1 / acosec(x);
  666. }
  667. /*************************************
  668. * Convert string to float
  669. */
  670. real atof(char[] s)
  671. {
  672. if (!s.length)
  673. return real.nan;
  674. real result = 0;
  675. size_t i = 0;
  676. while (s[i] == '\t' || s[i] == ' ')
  677. if (++i >= s.length)
  678. return real.nan;
  679. bool neg = false;
  680. if (s[i] == '-')
  681. {
  682. neg = true;
  683. i++;
  684. }
  685. else if (s[i] == '+')
  686. i++;
  687. if (i >= s.length)
  688. return real.nan;
  689. bool hex;
  690. if (s[s.length - 1] == 'h')
  691. {
  692. hex = true;
  693. s.length = s.length - 1;
  694. }
  695. else if (i + 1 < s.length && s[i] == '0' && s[i+1] == 'x')
  696. {
  697. hex = true;
  698. i += 2;
  699. if (i >= s.length)
  700. return real.nan;
  701. }
  702. else
  703. hex = false;
  704. while (s[i] != '.')
  705. {
  706. if (hex)
  707. {
  708. if ((s[i] == 'p' || s[i] == 'P'))
  709. break;
  710. result *= 0x10;
  711. }
  712. else
  713. {
  714. if ((s[i] == 'e' || s[i] == 'E'))
  715. break;
  716. result *= 10;
  717. }
  718. if (s[i] >= '0' && s[i] <= '9')
  719. result += s[i] - '0';
  720. else if (hex)
  721. {
  722. if (s[i] >= 'a' && s[i] <= 'f')
  723. result += s[i] - 'a' + 10;
  724. else if (s[i] >= 'A' && s[i] <= 'F')
  725. result += s[i] - 'A' + 10;
  726. else
  727. return real.nan;
  728. }
  729. else
  730. return real.nan;
  731. if (++i >= s.length)
  732. goto done;
  733. }
  734. if (s[i] == '.')
  735. {
  736. if (++i >= s.length)
  737. goto done;
  738. ulong k = 1;
  739. while (true)
  740. {
  741. if (hex)
  742. {
  743. if ((s[i] == 'p' || s[i] == 'P'))
  744. break;
  745. result *= 0x10;
  746. }
  747. else
  748. {
  749. if ((s[i] == 'e' || s[i] == 'E'))
  750. break;
  751. result *= 10;
  752. }
  753. k *= (hex ? 0x10 : 10);
  754. if (s[i] >= '0' && s[i] <= '9')
  755. result += s[i] - '0';
  756. else if (hex)
  757. {
  758. if (s[i] >= 'a' && s[i] <= 'f')
  759. result += s[i] - 'a' + 10;
  760. else if (s[i] >= 'A' && s[i] <= 'F')
  761. result += s[i] - 'A' + 10;
  762. else
  763. return real.nan;
  764. }
  765. else
  766. return real.nan;
  767. if (++i >= s.length)
  768. {
  769. result /= k;
  770. goto done;
  771. }
  772. }
  773. result /= k;
  774. }
  775. if (++i >= s.length)
  776. return real.nan;
  777. bool eneg = false;
  778. if (s[i] == '-')
  779. {
  780. eneg = true;
  781. i++;
  782. }
  783. else if (s[i] == '+')
  784. i++;
  785. if (i >= s.length)
  786. return real.nan;
  787. int e = 0;
  788. while (i < s.length)
  789. {
  790. e *= 10;
  791. if (s[i] >= '0' && s[i] <= '9')
  792. e += s[i] - '0';
  793. else
  794. return real.nan;
  795. i++;
  796. }
  797. if (eneg)
  798. e = -e;
  799. result *= std.math.pow(hex ? 2.0L : 10.0L, cast(real)e);
  800. done:
  801. return neg ? -result : result;
  802. }
  803. unittest
  804. {
  805. assert(feq(atof("123"), 123));
  806. assert(feq(atof("+123"), +123));
  807. assert(feq(atof("-123"), -123));
  808. assert(feq(atof("123e2"), 12300));
  809. assert(feq(atof("123e+2"), 12300));
  810. assert(feq(atof("123e-2"), 1.23));
  811. assert(feq(atof("123."), 123));
  812. assert(feq(atof("123.E-2"), 1.23));
  813. assert(feq(atof(".456"), .456));
  814. assert(feq(atof("123.456"), 123.456));
  815. assert(feq(atof("1.23456E+2"), 123.456));
  816. //assert(feq(atof("1A2h"), 1A2h));
  817. //assert(feq(atof("1a2h"), 1a2h));
  818. assert(feq(atof("0x1A2"), 0x1A2));
  819. assert(feq(atof("0x1a2p2"), 0x1a2p2));
  820. assert(feq(atof("0x1a2p+2"), 0x1a2p+2));
  821. assert(feq(atof("0x1a2p-2"), 0x1a2p-2));
  822. assert(feq(atof("0x1A2.3B4"), 0x1A2.3B4p0));
  823. assert(feq(atof("0x1a2.3b4P2"), 0x1a2.3b4P2));
  824. }