/std/math.d

http://github.com/jcd/phobos · D · 5827 lines · 3914 code · 563 blank · 1350 comment · 779 complexity · 9fbdeb980627c624e3f89cb331d11a13 MD5 · raw file

Large files are truncated click here to view the full file

  1. // Written in the D programming language.
  2. /**
  3. * Elementary mathematical functions
  4. *
  5. * Contains the elementary mathematical functions (powers, roots,
  6. * and trignometric functions), and low-level floating-point operations.
  7. * Mathematical special functions are available in std.mathspecial.
  8. *
  9. * The functionality closely follows the IEEE754-2008 standard for
  10. * floating-point arithmetic, including the use of camelCase names rather
  11. * than C99-style lower case names. All of these functions behave correctly
  12. * when presented with an infinity or NaN.
  13. *
  14. * Unlike C, there is no global 'errno' variable. Consequently, almost all of
  15. * these functions are pure nothrow.
  16. *
  17. * Status:
  18. * The semantics and names of feqrel and approxEqual will be revised.
  19. *
  20. * Macros:
  21. * WIKI = Phobos/StdMath
  22. *
  23. * TABLE_SV = <table border=1 cellpadding=4 cellspacing=0>
  24. * <caption>Special Values</caption>
  25. * $0</table>
  26. * SVH = $(TR $(TH $1) $(TH $2))
  27. * SV = $(TR $(TD $1) $(TD $2))
  28. *
  29. * NAN = $(RED NAN)
  30. * SUP = <span style="vertical-align:super;font-size:smaller">$0</span>
  31. * GAMMA = &#915;
  32. * THETA = &theta;
  33. * INTEGRAL = &#8747;
  34. * INTEGRATE = $(BIG &#8747;<sub>$(SMALL $1)</sub><sup>$2</sup>)
  35. * POWER = $1<sup>$2</sup>
  36. * SUB = $1<sub>$2</sub>
  37. * BIGSUM = $(BIG &Sigma; <sup>$2</sup><sub>$(SMALL $1)</sub>)
  38. * CHOOSE = $(BIG &#40;) <sup>$(SMALL $1)</sup><sub>$(SMALL $2)</sub> $(BIG &#41;)
  39. * PLUSMN = &plusmn;
  40. * INFIN = &infin;
  41. * PLUSMNINF = &plusmn;&infin;
  42. * PI = &pi;
  43. * LT = &lt;
  44. * GT = &gt;
  45. * SQRT = &radic;
  46. * HALF = &frac12;
  47. *
  48. * Copyright: Copyright Digital Mars 2000 - 2011.
  49. * D implementations of tan, atan, atan2, exp, expm1, exp2, log, log10, log1p,
  50. * log2, floor, ceil and lrint functions are based on the CEPHES math library,
  51. * which is Copyright (C) 2001 Stephen L. Moshier <steve@moshier.net>
  52. * and are incorporated herein by permission of the author. The author
  53. * reserves the right to distribute this material elsewhere under different
  54. * copying permissions. These modifications are distributed here under
  55. * the following terms:
  56. * License: <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>.
  57. * Authors: $(WEB digitalmars.com, Walter Bright),
  58. * Don Clugston, Conversion of CEPHES math library to D by Iain Buclaw
  59. * Source: $(PHOBOSSRC std/_math.d)
  60. */
  61. module std.math;
  62. import core.stdc.math;
  63. import std.traits;
  64. version(unittest)
  65. {
  66. import std.typetuple;
  67. }
  68. version(LDC)
  69. {
  70. import ldc.intrinsics;
  71. }
  72. version(DigitalMars)
  73. {
  74. version = INLINE_YL2X; // x87 has opcodes for these
  75. }
  76. version (X86)
  77. {
  78. version = X86_Any;
  79. }
  80. version (X86_64)
  81. {
  82. version = X86_Any;
  83. }
  84. version(D_InlineAsm_X86)
  85. {
  86. version = InlineAsm_X86_Any;
  87. }
  88. else version(D_InlineAsm_X86_64)
  89. {
  90. version = InlineAsm_X86_Any;
  91. }
  92. version(unittest)
  93. {
  94. import core.stdc.stdio;
  95. static if(real.sizeof > double.sizeof)
  96. enum uint useDigits = 16;
  97. else
  98. enum uint useDigits = 15;
  99. /******************************************
  100. * Compare floating point numbers to n decimal digits of precision.
  101. * Returns:
  102. * 1 match
  103. * 0 nomatch
  104. */
  105. private bool equalsDigit(real x, real y, uint ndigits)
  106. {
  107. if (signbit(x) != signbit(y))
  108. return 0;
  109. if (isinf(x) && isinf(y))
  110. return 1;
  111. if (isinf(x) || isinf(y))
  112. return 0;
  113. if (isnan(x) && isnan(y))
  114. return 1;
  115. if (isnan(x) || isnan(y))
  116. return 0;
  117. char[30] bufx;
  118. char[30] bufy;
  119. assert(ndigits < bufx.length);
  120. int ix;
  121. int iy;
  122. ix = sprintf(bufx.ptr, "%.*Lg", ndigits, x);
  123. assert(ix < bufx.length && ix > 0);
  124. iy = sprintf(bufy.ptr, "%.*Lg", ndigits, y);
  125. assert(ix < bufy.length && ix > 0);
  126. return bufx[0 .. ix] == bufy[0 .. iy];
  127. }
  128. }
  129. private:
  130. /*
  131. * The following IEEE 'real' formats are currently supported:
  132. * 64 bit Big-endian 'double' (eg PowerPC)
  133. * 128 bit Big-endian 'quadruple' (eg SPARC)
  134. * 64 bit Little-endian 'double' (eg x86-SSE2)
  135. * 80 bit Little-endian, with implied bit 'real80' (eg x87, Itanium).
  136. * 128 bit Little-endian 'quadruple' (not implemented on any known processor!)
  137. *
  138. * Non-IEEE 128 bit Big-endian 'doubledouble' (eg PowerPC) has partial support
  139. */
  140. version(LittleEndian)
  141. {
  142. static assert(real.mant_dig == 53 || real.mant_dig==64
  143. || real.mant_dig == 113,
  144. "Only 64-bit, 80-bit, and 128-bit reals"
  145. " are supported for LittleEndian CPUs");
  146. }
  147. else
  148. {
  149. static assert(real.mant_dig == 53 || real.mant_dig==106
  150. || real.mant_dig == 113,
  151. "Only 64-bit and 128-bit reals are supported for BigEndian CPUs."
  152. " double-double reals have partial support");
  153. }
  154. // Constants used for extracting the components of the representation.
  155. // They supplement the built-in floating point properties.
  156. template floatTraits(T)
  157. {
  158. // EXPMASK is a ushort mask to select the exponent portion (without sign)
  159. // EXPPOS_SHORT is the index of the exponent when represented as a ushort array.
  160. // SIGNPOS_BYTE is the index of the sign when represented as a ubyte array.
  161. // RECIP_EPSILON is the value such that (smallest_subnormal) * RECIP_EPSILON == T.min_normal
  162. enum T RECIP_EPSILON = (1/T.epsilon);
  163. static if (T.mant_dig == 24)
  164. { // float
  165. enum ushort EXPMASK = 0x7F80;
  166. enum ushort EXPBIAS = 0x3F00;
  167. enum uint EXPMASK_INT = 0x7F80_0000;
  168. enum uint MANTISSAMASK_INT = 0x007F_FFFF;
  169. version(LittleEndian)
  170. {
  171. enum EXPPOS_SHORT = 1;
  172. }
  173. else
  174. {
  175. enum EXPPOS_SHORT = 0;
  176. }
  177. }
  178. else static if (T.mant_dig == 53) // double, or real==double
  179. {
  180. enum ushort EXPMASK = 0x7FF0;
  181. enum ushort EXPBIAS = 0x3FE0;
  182. enum uint EXPMASK_INT = 0x7FF0_0000;
  183. enum uint MANTISSAMASK_INT = 0x000F_FFFF; // for the MSB only
  184. version(LittleEndian)
  185. {
  186. enum EXPPOS_SHORT = 3;
  187. enum SIGNPOS_BYTE = 7;
  188. }
  189. else
  190. {
  191. enum EXPPOS_SHORT = 0;
  192. enum SIGNPOS_BYTE = 0;
  193. }
  194. }
  195. else static if (T.mant_dig == 64) // real80
  196. {
  197. enum ushort EXPMASK = 0x7FFF;
  198. enum ushort EXPBIAS = 0x3FFE;
  199. version(LittleEndian)
  200. {
  201. enum EXPPOS_SHORT = 4;
  202. enum SIGNPOS_BYTE = 9;
  203. }
  204. else
  205. {
  206. enum EXPPOS_SHORT = 0;
  207. enum SIGNPOS_BYTE = 0;
  208. }
  209. }
  210. else static if (T.mant_dig == 113) // quadruple
  211. {
  212. enum ushort EXPMASK = 0x7FFF;
  213. version(LittleEndian)
  214. {
  215. enum EXPPOS_SHORT = 7;
  216. enum SIGNPOS_BYTE = 15;
  217. }
  218. else
  219. {
  220. enum EXPPOS_SHORT = 0;
  221. enum SIGNPOS_BYTE = 0;
  222. }
  223. }
  224. else static if (T.mant_dig == 106) // doubledouble
  225. {
  226. enum ushort EXPMASK = 0x7FF0;
  227. // the exponent byte is not unique
  228. version(LittleEndian)
  229. {
  230. enum EXPPOS_SHORT = 7; // [3] is also an exp short
  231. enum SIGNPOS_BYTE = 15;
  232. }
  233. else
  234. {
  235. enum EXPPOS_SHORT = 0; // [4] is also an exp short
  236. enum SIGNPOS_BYTE = 0;
  237. }
  238. }
  239. }
  240. // These apply to all floating-point types
  241. version(LittleEndian)
  242. {
  243. enum MANTISSA_LSB = 0;
  244. enum MANTISSA_MSB = 1;
  245. }
  246. else
  247. {
  248. enum MANTISSA_LSB = 1;
  249. enum MANTISSA_MSB = 0;
  250. }
  251. public:
  252. // Values obtained from Wolfram Alpha. 116 bits ought to be enough for anybody.
  253. // Wolfram Alpha LLC. 2011. Wolfram|Alpha. http://www.wolframalpha.com/input/?i=e+in+base+16 (access July 6, 2011).
  254. enum real E = 0x1.5bf0a8b1457695355fb8ac404e7a8p+1L; /** e = 2.718281... */
  255. enum real LOG2T = 0x1.a934f0979a3715fc9257edfe9b5fbp+1L; /** $(SUB log, 2)10 = 3.321928... */
  256. enum real LOG2E = 0x1.71547652b82fe1777d0ffda0d23a8p+0L; /** $(SUB log, 2)e = 1.442695... */
  257. enum real LOG2 = 0x1.34413509f79fef311f12b35816f92p-2L; /** $(SUB log, 10)2 = 0.301029... */
  258. enum real LOG10E = 0x1.bcb7b1526e50e32a6ab7555f5a67cp-2L; /** $(SUB log, 10)e = 0.434294... */
  259. enum real LN2 = 0x1.62e42fefa39ef35793c7673007e5fp-1L; /** ln 2 = 0.693147... */
  260. enum real LN10 = 0x1.26bb1bbb5551582dd4adac5705a61p+1L; /** ln 10 = 2.302585... */
  261. enum real PI = 0x1.921fb54442d18469898cc51701b84p+1L; /** $(_PI) = 3.141592... */
  262. enum real PI_2 = PI/2; /** $(PI) / 2 = 1.570796... */
  263. enum real PI_4 = PI/4; /** $(PI) / 4 = 0.785398... */
  264. enum real M_1_PI = 0x1.45f306dc9c882a53f84eafa3ea69cp-2L; /** 1 / $(PI) = 0.318309... */
  265. enum real M_2_PI = 2*M_1_PI; /** 2 / $(PI) = 0.636619... */
  266. enum real M_2_SQRTPI = 0x1.20dd750429b6d11ae3a914fed7fd8p+0L; /** 2 / $(SQRT)$(PI) = 1.128379... */
  267. enum real SQRT2 = 0x1.6a09e667f3bcc908b2fb1366ea958p+0L; /** $(SQRT)2 = 1.414213... */
  268. enum real SQRT1_2 = SQRT2/2; /** $(SQRT)$(HALF) = 0.707106... */
  269. // Note: Make sure the magic numbers in compiler backend for x87 match these.
  270. /***********************************
  271. * Calculates the absolute value
  272. *
  273. * For complex numbers, abs(z) = sqrt( $(POWER z.re, 2) + $(POWER z.im, 2) )
  274. * = hypot(z.re, z.im).
  275. */
  276. Num abs(Num)(Num x) @safe pure nothrow
  277. if (is(typeof(Num.init >= 0)) && is(typeof(-Num.init)) &&
  278. !(is(Num* : const(ifloat*)) || is(Num* : const(idouble*))
  279. || is(Num* : const(ireal*))))
  280. {
  281. static if (isFloatingPoint!(Num))
  282. return fabs(x);
  283. else
  284. return x>=0 ? x : -x;
  285. }
  286. auto abs(Num)(Num z) @safe pure nothrow
  287. if (is(Num* : const(cfloat*)) || is(Num* : const(cdouble*))
  288. || is(Num* : const(creal*)))
  289. {
  290. return hypot(z.re, z.im);
  291. }
  292. /** ditto */
  293. real abs(Num)(Num y) @safe pure nothrow
  294. if (is(Num* : const(ifloat*)) || is(Num* : const(idouble*))
  295. || is(Num* : const(ireal*)))
  296. {
  297. return fabs(y.im);
  298. }
  299. unittest
  300. {
  301. assert(isIdentical(abs(-0.0L), 0.0L));
  302. assert(isNaN(abs(real.nan)));
  303. assert(abs(-real.infinity) == real.infinity);
  304. assert(abs(-3.2Li) == 3.2L);
  305. assert(abs(71.6Li) == 71.6L);
  306. assert(abs(-56) == 56);
  307. assert(abs(2321312L) == 2321312L);
  308. assert(abs(-1+1i) == sqrt(2.0L));
  309. }
  310. /***********************************
  311. * Complex conjugate
  312. *
  313. * conj(x + iy) = x - iy
  314. *
  315. * Note that z * conj(z) = $(POWER z.re, 2) - $(POWER z.im, 2)
  316. * is always a real number
  317. */
  318. creal conj(creal z) @safe pure nothrow
  319. {
  320. return z.re - z.im*1i;
  321. }
  322. /** ditto */
  323. ireal conj(ireal y) @safe pure nothrow
  324. {
  325. return -y;
  326. }
  327. unittest
  328. {
  329. assert(conj(7 + 3i) == 7-3i);
  330. ireal z = -3.2Li;
  331. assert(conj(z) == -z);
  332. }
  333. /***********************************
  334. * Returns cosine of x. x is in radians.
  335. *
  336. * $(TABLE_SV
  337. * $(TR $(TH x) $(TH cos(x)) $(TH invalid?))
  338. * $(TR $(TD $(NAN)) $(TD $(NAN)) $(TD yes) )
  339. * $(TR $(TD $(PLUSMN)$(INFIN)) $(TD $(NAN)) $(TD yes) )
  340. * )
  341. * Bugs:
  342. * Results are undefined if |x| >= $(POWER 2,64).
  343. */
  344. real cos(real x) @safe pure nothrow; /* intrinsic */
  345. /***********************************
  346. * Returns sine of x. x is in radians.
  347. *
  348. * $(TABLE_SV
  349. * $(TR $(TH x) $(TH sin(x)) $(TH invalid?))
  350. * $(TR $(TD $(NAN)) $(TD $(NAN)) $(TD yes))
  351. * $(TR $(TD $(PLUSMN)0.0) $(TD $(PLUSMN)0.0) $(TD no))
  352. * $(TR $(TD $(PLUSMNINF)) $(TD $(NAN)) $(TD yes))
  353. * )
  354. * Bugs:
  355. * Results are undefined if |x| >= $(POWER 2,64).
  356. */
  357. real sin(real x) @safe pure nothrow; /* intrinsic */
  358. /***********************************
  359. * sine, complex and imaginary
  360. *
  361. * sin(z) = sin(z.re)*cosh(z.im) + cos(z.re)*sinh(z.im)i
  362. *
  363. * If both sin($(THETA)) and cos($(THETA)) are required,
  364. * it is most efficient to use expi($(THETA)).
  365. */
  366. creal sin(creal z) @safe pure nothrow
  367. {
  368. creal cs = expi(z.re);
  369. creal csh = coshisinh(z.im);
  370. return cs.im * csh.re + cs.re * csh.im * 1i;
  371. }
  372. /** ditto */
  373. ireal sin(ireal y) @safe pure nothrow
  374. {
  375. return cosh(y.im)*1i;
  376. }
  377. unittest
  378. {
  379. assert(sin(0.0+0.0i) == 0.0);
  380. assert(sin(2.0+0.0i) == sin(2.0L) );
  381. }
  382. /***********************************
  383. * cosine, complex and imaginary
  384. *
  385. * cos(z) = cos(z.re)*cosh(z.im) - sin(z.re)*sinh(z.im)i
  386. */
  387. creal cos(creal z) @safe pure nothrow
  388. {
  389. creal cs = expi(z.re);
  390. creal csh = coshisinh(z.im);
  391. return cs.re * csh.re - cs.im * csh.im * 1i;
  392. }
  393. /** ditto */
  394. real cos(ireal y) @safe pure nothrow
  395. {
  396. return cosh(y.im);
  397. }
  398. unittest
  399. {
  400. assert(cos(0.0+0.0i)==1.0);
  401. assert(cos(1.3L+0.0i)==cos(1.3L));
  402. assert(cos(5.2Li)== cosh(5.2L));
  403. }
  404. /****************************************************************************
  405. * Returns tangent of x. x is in radians.
  406. *
  407. * $(TABLE_SV
  408. * $(TR $(TH x) $(TH tan(x)) $(TH invalid?))
  409. * $(TR $(TD $(NAN)) $(TD $(NAN)) $(TD yes))
  410. * $(TR $(TD $(PLUSMN)0.0) $(TD $(PLUSMN)0.0) $(TD no))
  411. * $(TR $(TD $(PLUSMNINF)) $(TD $(NAN)) $(TD yes))
  412. * )
  413. */
  414. real tan(real x) @trusted pure nothrow
  415. {
  416. version(D_InlineAsm_X86)
  417. {
  418. asm
  419. {
  420. fld x[EBP] ; // load theta
  421. fxam ; // test for oddball values
  422. fstsw AX ;
  423. sahf ;
  424. jc trigerr ; // x is NAN, infinity, or empty
  425. // 387's can handle subnormals
  426. SC18: fptan ;
  427. fstp ST(0) ; // dump X, which is always 1
  428. fstsw AX ;
  429. sahf ;
  430. jnp Lret ; // C2 = 1 (x is out of range)
  431. // Do argument reduction to bring x into range
  432. fldpi ;
  433. fxch ;
  434. SC17: fprem1 ;
  435. fstsw AX ;
  436. sahf ;
  437. jp SC17 ;
  438. fstp ST(1) ; // remove pi from stack
  439. jmp SC18 ;
  440. trigerr:
  441. jnp Lret ; // if theta is NAN, return theta
  442. fstp ST(0) ; // dump theta
  443. }
  444. return real.nan;
  445. Lret: {}
  446. }
  447. else version(D_InlineAsm_X86_64)
  448. {
  449. version (Win64)
  450. {
  451. asm
  452. {
  453. fld real ptr [RCX] ; // load theta
  454. }
  455. }
  456. else
  457. {
  458. asm
  459. {
  460. fld x[RBP] ; // load theta
  461. }
  462. }
  463. asm
  464. {
  465. fxam ; // test for oddball values
  466. fstsw AX ;
  467. test AH,1 ;
  468. jnz trigerr ; // x is NAN, infinity, or empty
  469. // 387's can handle subnormals
  470. SC18: fptan ;
  471. fstp ST(0) ; // dump X, which is always 1
  472. fstsw AX ;
  473. test AH,4 ;
  474. jz Lret ; // C2 = 1 (x is out of range)
  475. // Do argument reduction to bring x into range
  476. fldpi ;
  477. fxch ;
  478. SC17: fprem1 ;
  479. fstsw AX ;
  480. test AH,4 ;
  481. jnz SC17 ;
  482. fstp ST(1) ; // remove pi from stack
  483. jmp SC18 ;
  484. trigerr:
  485. test AH,4 ;
  486. jz Lret ; // if theta is NAN, return theta
  487. fstp ST(0) ; // dump theta
  488. }
  489. return real.nan;
  490. Lret: {}
  491. }
  492. else
  493. {
  494. // Coefficients for tan(x)
  495. static immutable real[3] P = [
  496. -1.7956525197648487798769E7L,
  497. 1.1535166483858741613983E6L,
  498. -1.3093693918138377764608E4L,
  499. ];
  500. static immutable real[5] Q = [
  501. -5.3869575592945462988123E7L,
  502. 2.5008380182335791583922E7L,
  503. -1.3208923444021096744731E6L,
  504. 1.3681296347069295467845E4L,
  505. 1.0000000000000000000000E0L,
  506. ];
  507. // PI/4 split into three parts.
  508. enum real P1 = 7.853981554508209228515625E-1L;
  509. enum real P2 = 7.946627356147928367136046290398E-9L;
  510. enum real P3 = 3.061616997868382943065164830688E-17L;
  511. // Special cases.
  512. if (x == 0.0 || isNaN(x))
  513. return x;
  514. if (isInfinity(x))
  515. return real.nan;
  516. // Make argument positive but save the sign.
  517. bool sign = false;
  518. if (signbit(x))
  519. {
  520. sign = true;
  521. x = -x;
  522. }
  523. // Compute x mod PI/4.
  524. real y = floor(x / PI_4);
  525. // Strip high bits of integer part.
  526. real z = ldexp(y, -4);
  527. // Compute y - 16 * (y / 16).
  528. z = y - ldexp(floor(z), 4);
  529. // Integer and fraction part modulo one octant.
  530. int j = cast(int)(z);
  531. // Map zeros and singularities to origin.
  532. if (j & 1)
  533. {
  534. j += 1;
  535. y += 1.0;
  536. }
  537. z = ((x - y * P1) - y * P2) - y * P3;
  538. real zz = z * z;
  539. if (zz > 1.0e-20L)
  540. y = z + z * (zz * poly(zz, P) / poly(zz, Q));
  541. else
  542. y = z;
  543. if (j & 2)
  544. y = -1.0 / y;
  545. return (sign) ? -y : y;
  546. }
  547. }
  548. unittest
  549. {
  550. static real[2][] vals = // angle,tan
  551. [
  552. [ 0, 0],
  553. [ .5, .5463024898],
  554. [ 1, 1.557407725],
  555. [ 1.5, 14.10141995],
  556. [ 2, -2.185039863],
  557. [ 2.5,-.7470222972],
  558. [ 3, -.1425465431],
  559. [ 3.5, .3745856402],
  560. [ 4, 1.157821282],
  561. [ 4.5, 4.637332055],
  562. [ 5, -3.380515006],
  563. [ 5.5,-.9955840522],
  564. [ 6, -.2910061914],
  565. [ 6.5, .2202772003],
  566. [ 10, .6483608275],
  567. // special angles
  568. [ PI_4, 1],
  569. //[ PI_2, real.infinity], // PI_2 is not _exactly_ pi/2.
  570. [ 3*PI_4, -1],
  571. [ PI, 0],
  572. [ 5*PI_4, 1],
  573. //[ 3*PI_2, -real.infinity],
  574. [ 7*PI_4, -1],
  575. [ 2*PI, 0],
  576. ];
  577. int i;
  578. for (i = 0; i < vals.length; i++)
  579. {
  580. real x = vals[i][0];
  581. real r = vals[i][1];
  582. real t = tan(x);
  583. //printf("tan(%Lg) = %Lg, should be %Lg\n", x, t, r);
  584. if (!isIdentical(r, t)) assert(fabs(r-t) <= .0000001);
  585. x = -x;
  586. r = -r;
  587. t = tan(x);
  588. //printf("tan(%Lg) = %Lg, should be %Lg\n", x, t, r);
  589. if (!isIdentical(r, t) && !(r!=r && t!=t)) assert(fabs(r-t) <= .0000001);
  590. }
  591. // overflow
  592. assert(isNaN(tan(real.infinity)));
  593. assert(isNaN(tan(-real.infinity)));
  594. // NaN propagation
  595. assert(isIdentical( tan(NaN(0x0123L)), NaN(0x0123L) ));
  596. }
  597. unittest
  598. {
  599. assert(equalsDigit(tan(PI / 3), std.math.sqrt(3.0), useDigits));
  600. }
  601. /***************
  602. * Calculates the arc cosine of x,
  603. * returning a value ranging from 0 to $(PI).
  604. *
  605. * $(TABLE_SV
  606. * $(TR $(TH x) $(TH acos(x)) $(TH invalid?))
  607. * $(TR $(TD $(GT)1.0) $(TD $(NAN)) $(TD yes))
  608. * $(TR $(TD $(LT)-1.0) $(TD $(NAN)) $(TD yes))
  609. * $(TR $(TD $(NAN)) $(TD $(NAN)) $(TD yes))
  610. * )
  611. */
  612. real acos(real x) @safe pure nothrow
  613. {
  614. return atan2(sqrt(1-x*x), x);
  615. }
  616. /// ditto
  617. double acos(double x) @safe pure nothrow { return acos(cast(real)x); }
  618. /// ditto
  619. float acos(float x) @safe pure nothrow { return acos(cast(real)x); }
  620. unittest
  621. {
  622. assert(equalsDigit(acos(0.5), std.math.PI / 3, useDigits));
  623. }
  624. /***************
  625. * Calculates the arc sine of x,
  626. * returning a value ranging from -$(PI)/2 to $(PI)/2.
  627. *
  628. * $(TABLE_SV
  629. * $(TR $(TH x) $(TH asin(x)) $(TH invalid?))
  630. * $(TR $(TD $(PLUSMN)0.0) $(TD $(PLUSMN)0.0) $(TD no))
  631. * $(TR $(TD $(GT)1.0) $(TD $(NAN)) $(TD yes))
  632. * $(TR $(TD $(LT)-1.0) $(TD $(NAN)) $(TD yes))
  633. * )
  634. */
  635. real asin(real x) @safe pure nothrow
  636. {
  637. return atan2(x, sqrt(1-x*x));
  638. }
  639. /// ditto
  640. double asin(double x) @safe pure nothrow { return asin(cast(real)x); }
  641. /// ditto
  642. float asin(float x) @safe pure nothrow { return asin(cast(real)x); }
  643. unittest
  644. {
  645. assert(equalsDigit(asin(0.5), PI / 6, useDigits));
  646. }
  647. /***************
  648. * Calculates the arc tangent of x,
  649. * returning a value ranging from -$(PI)/2 to $(PI)/2.
  650. *
  651. * $(TABLE_SV
  652. * $(TR $(TH x) $(TH atan(x)) $(TH invalid?))
  653. * $(TR $(TD $(PLUSMN)0.0) $(TD $(PLUSMN)0.0) $(TD no))
  654. * $(TR $(TD $(PLUSMN)$(INFIN)) $(TD $(NAN)) $(TD yes))
  655. * )
  656. */
  657. real atan(real x) @safe pure nothrow
  658. {
  659. version(InlineAsm_X86_Any)
  660. {
  661. return atan2(x, 1.0L);
  662. }
  663. else
  664. {
  665. // Coefficients for atan(x)
  666. static immutable real[5] P = [
  667. -5.0894116899623603312185E1L,
  668. -9.9988763777265819915721E1L,
  669. -6.3976888655834347413154E1L,
  670. -1.4683508633175792446076E1L,
  671. -8.6863818178092187535440E-1L,
  672. ];
  673. static immutable real[6] Q = [
  674. 1.5268235069887081006606E2L,
  675. 3.9157570175111990631099E2L,
  676. 3.6144079386152023162701E2L,
  677. 1.4399096122250781605352E2L,
  678. 2.2981886733594175366172E1L,
  679. 1.0000000000000000000000E0L,
  680. ];
  681. // tan(PI/8)
  682. enum real TAN_PI_8 = 4.1421356237309504880169e-1L;
  683. // tan(3 * PI/8)
  684. enum real TAN3_PI_8 = 2.41421356237309504880169L;
  685. // Special cases.
  686. if (x == 0.0)
  687. return x;
  688. if (isInfinity(x))
  689. return copysign(PI_2, x);
  690. // Make argument positive but save the sign.
  691. bool sign = false;
  692. if (signbit(x))
  693. {
  694. sign = true;
  695. x = -x;
  696. }
  697. // Range reduction.
  698. real y;
  699. if (x > TAN3_PI_8)
  700. {
  701. y = PI_2;
  702. x = -(1.0 / x);
  703. }
  704. else if (x > TAN_PI_8)
  705. {
  706. y = PI_4;
  707. x = (x - 1.0)/(x + 1.0);
  708. }
  709. else
  710. y = 0.0;
  711. // Rational form in x^^2.
  712. real z = x * x;
  713. y = y + (poly(z, P) / poly(z, Q)) * z * x + x;
  714. return (sign) ? -y : y;
  715. }
  716. }
  717. /// ditto
  718. double atan(double x) @safe pure nothrow { return atan(cast(real)x); }
  719. /// ditto
  720. float atan(float x) @safe pure nothrow { return atan(cast(real)x); }
  721. unittest
  722. {
  723. assert(equalsDigit(atan(std.math.sqrt(3.0)), PI / 3, useDigits));
  724. }
  725. /***************
  726. * Calculates the arc tangent of y / x,
  727. * returning a value ranging from -$(PI) to $(PI).
  728. *
  729. * $(TABLE_SV
  730. * $(TR $(TH y) $(TH x) $(TH atan(y, x)))
  731. * $(TR $(TD $(NAN)) $(TD anything) $(TD $(NAN)) )
  732. * $(TR $(TD anything) $(TD $(NAN)) $(TD $(NAN)) )
  733. * $(TR $(TD $(PLUSMN)0.0) $(TD $(GT)0.0) $(TD $(PLUSMN)0.0) )
  734. * $(TR $(TD $(PLUSMN)0.0) $(TD +0.0) $(TD $(PLUSMN)0.0) )
  735. * $(TR $(TD $(PLUSMN)0.0) $(TD $(LT)0.0) $(TD $(PLUSMN)$(PI)))
  736. * $(TR $(TD $(PLUSMN)0.0) $(TD -0.0) $(TD $(PLUSMN)$(PI)))
  737. * $(TR $(TD $(GT)0.0) $(TD $(PLUSMN)0.0) $(TD $(PI)/2) )
  738. * $(TR $(TD $(LT)0.0) $(TD $(PLUSMN)0.0) $(TD -$(PI)/2) )
  739. * $(TR $(TD $(GT)0.0) $(TD $(INFIN)) $(TD $(PLUSMN)0.0) )
  740. * $(TR $(TD $(PLUSMN)$(INFIN)) $(TD anything) $(TD $(PLUSMN)$(PI)/2))
  741. * $(TR $(TD $(GT)0.0) $(TD -$(INFIN)) $(TD $(PLUSMN)$(PI)) )
  742. * $(TR $(TD $(PLUSMN)$(INFIN)) $(TD $(INFIN)) $(TD $(PLUSMN)$(PI)/4))
  743. * $(TR $(TD $(PLUSMN)$(INFIN)) $(TD -$(INFIN)) $(TD $(PLUSMN)3$(PI)/4))
  744. * )
  745. */
  746. real atan2(real y, real x) @trusted pure nothrow
  747. {
  748. version(InlineAsm_X86_Any)
  749. {
  750. version (Win64)
  751. {
  752. asm {
  753. naked;
  754. fld real ptr [RDX]; // y
  755. fld real ptr [RCX]; // x
  756. fpatan;
  757. ret;
  758. }
  759. }
  760. else
  761. {
  762. asm {
  763. fld y;
  764. fld x;
  765. fpatan;
  766. }
  767. }
  768. }
  769. else
  770. {
  771. // Special cases.
  772. if (isNaN(x) || isNaN(y))
  773. return real.nan;
  774. if (y == 0.0)
  775. {
  776. if (x >= 0 && !signbit(x))
  777. return copysign(0, y);
  778. else
  779. return copysign(PI, y);
  780. }
  781. if (x == 0.0)
  782. return copysign(PI_2, y);
  783. if (isInfinity(x))
  784. {
  785. if (signbit(x))
  786. {
  787. if (isInfinity(y))
  788. return copysign(3*PI_4, y);
  789. else
  790. return copysign(PI, y);
  791. }
  792. else
  793. {
  794. if (isInfinity(y))
  795. return copysign(PI_4, y);
  796. else
  797. return copysign(0.0, y);
  798. }
  799. }
  800. if (isInfinity(y))
  801. return copysign(PI_2, y);
  802. // Call atan and determine the quadrant.
  803. real z = atan(y / x);
  804. if (signbit(x))
  805. {
  806. if (signbit(y))
  807. z = z - PI;
  808. else
  809. z = z + PI;
  810. }
  811. if (z == 0.0)
  812. return copysign(z, y);
  813. return z;
  814. }
  815. }
  816. /// ditto
  817. double atan2(double y, double x) @safe pure nothrow
  818. {
  819. return atan2(cast(real)y, cast(real)x);
  820. }
  821. /// ditto
  822. float atan2(float y, float x) @safe pure nothrow
  823. {
  824. return atan2(cast(real)y, cast(real)x);
  825. }
  826. unittest
  827. {
  828. assert(equalsDigit(atan2(1.0L, std.math.sqrt(3.0L)), PI / 6, useDigits));
  829. }
  830. /***********************************
  831. * Calculates the hyperbolic cosine of x.
  832. *
  833. * $(TABLE_SV
  834. * $(TR $(TH x) $(TH cosh(x)) $(TH invalid?))
  835. * $(TR $(TD $(PLUSMN)$(INFIN)) $(TD $(PLUSMN)0.0) $(TD no) )
  836. * )
  837. */
  838. real cosh(real x) @safe pure nothrow
  839. {
  840. // cosh = (exp(x)+exp(-x))/2.
  841. // The naive implementation works correctly.
  842. real y = exp(x);
  843. return (y + 1.0/y) * 0.5;
  844. }
  845. /// ditto
  846. double cosh(double x) @safe pure nothrow { return cosh(cast(real)x); }
  847. /// ditto
  848. float cosh(float x) @safe pure nothrow { return cosh(cast(real)x); }
  849. unittest
  850. {
  851. assert(equalsDigit(cosh(1.0), (E + 1.0 / E) / 2, useDigits));
  852. }
  853. /***********************************
  854. * Calculates the hyperbolic sine of x.
  855. *
  856. * $(TABLE_SV
  857. * $(TR $(TH x) $(TH sinh(x)) $(TH invalid?))
  858. * $(TR $(TD $(PLUSMN)0.0) $(TD $(PLUSMN)0.0) $(TD no))
  859. * $(TR $(TD $(PLUSMN)$(INFIN)) $(TD $(PLUSMN)$(INFIN)) $(TD no))
  860. * )
  861. */
  862. real sinh(real x) @safe pure nothrow
  863. {
  864. // sinh(x) = (exp(x)-exp(-x))/2;
  865. // Very large arguments could cause an overflow, but
  866. // the maximum value of x for which exp(x) + exp(-x)) != exp(x)
  867. // is x = 0.5 * (real.mant_dig) * LN2. // = 22.1807 for real80.
  868. if (fabs(x) > real.mant_dig * LN2)
  869. {
  870. return copysign(0.5 * exp(fabs(x)), x);
  871. }
  872. real y = expm1(x);
  873. return 0.5 * y / (y+1) * (y+2);
  874. }
  875. /// ditto
  876. double sinh(double x) @safe pure nothrow { return sinh(cast(real)x); }
  877. /// ditto
  878. float sinh(float x) @safe pure nothrow { return sinh(cast(real)x); }
  879. unittest
  880. {
  881. assert(equalsDigit(sinh(1.0), (E - 1.0 / E) / 2, useDigits));
  882. }
  883. /***********************************
  884. * Calculates the hyperbolic tangent of x.
  885. *
  886. * $(TABLE_SV
  887. * $(TR $(TH x) $(TH tanh(x)) $(TH invalid?))
  888. * $(TR $(TD $(PLUSMN)0.0) $(TD $(PLUSMN)0.0) $(TD no) )
  889. * $(TR $(TD $(PLUSMN)$(INFIN)) $(TD $(PLUSMN)1.0) $(TD no))
  890. * )
  891. */
  892. real tanh(real x) @safe pure nothrow
  893. {
  894. // tanh(x) = (exp(x) - exp(-x))/(exp(x)+exp(-x))
  895. if (fabs(x) > real.mant_dig * LN2)
  896. {
  897. return copysign(1, x);
  898. }
  899. real y = expm1(2*x);
  900. return y / (y + 2);
  901. }
  902. /// ditto
  903. double tanh(double x) @safe pure nothrow { return tanh(cast(real)x); }
  904. /// ditto
  905. float tanh(float x) @safe pure nothrow { return tanh(cast(real)x); }
  906. unittest
  907. {
  908. assert(equalsDigit(tanh(1.0), sinh(1.0) / cosh(1.0), 15));
  909. }
  910. package:
  911. /* Returns cosh(x) + I * sinh(x)
  912. * Only one call to exp() is performed.
  913. */
  914. creal coshisinh(real x) @safe pure nothrow
  915. {
  916. // See comments for cosh, sinh.
  917. if (fabs(x) > real.mant_dig * LN2)
  918. {
  919. real y = exp(fabs(x));
  920. return y * 0.5 + 0.5i * copysign(y, x);
  921. }
  922. else
  923. {
  924. real y = expm1(x);
  925. return (y + 1.0 + 1.0/(y + 1.0)) * 0.5 + 0.5i * y / (y+1) * (y+2);
  926. }
  927. }
  928. unittest
  929. {
  930. creal c = coshisinh(3.0L);
  931. assert(c.re == cosh(3.0L));
  932. assert(c.im == sinh(3.0L));
  933. }
  934. public:
  935. /***********************************
  936. * Calculates the inverse hyperbolic cosine of x.
  937. *
  938. * Mathematically, acosh(x) = log(x + sqrt( x*x - 1))
  939. *
  940. * $(TABLE_DOMRG
  941. * $(DOMAIN 1..$(INFIN))
  942. * $(RANGE 1..log(real.max), $(INFIN)) )
  943. * $(TABLE_SV
  944. * $(SVH x, acosh(x) )
  945. * $(SV $(NAN), $(NAN) )
  946. * $(SV $(LT)1, $(NAN) )
  947. * $(SV 1, 0 )
  948. * $(SV +$(INFIN),+$(INFIN))
  949. * )
  950. */
  951. real acosh(real x) @safe pure nothrow
  952. {
  953. if (x > 1/real.epsilon)
  954. return LN2 + log(x);
  955. else
  956. return log(x + sqrt(x*x - 1));
  957. }
  958. /// ditto
  959. double acosh(double x) @safe pure nothrow { return acosh(cast(real)x); }
  960. /// ditto
  961. float acosh(float x) @safe pure nothrow { return acosh(cast(real)x); }
  962. unittest
  963. {
  964. assert(isNaN(acosh(0.9)));
  965. assert(isNaN(acosh(real.nan)));
  966. assert(acosh(1.0)==0.0);
  967. assert(acosh(real.infinity) == real.infinity);
  968. assert(isNaN(acosh(0.5)));
  969. assert(equalsDigit(acosh(cosh(3.0)), 3, useDigits));
  970. }
  971. /***********************************
  972. * Calculates the inverse hyperbolic sine of x.
  973. *
  974. * Mathematically,
  975. * ---------------
  976. * asinh(x) = log( x + sqrt( x*x + 1 )) // if x >= +0
  977. * asinh(x) = -log(-x + sqrt( x*x + 1 )) // if x <= -0
  978. * -------------
  979. *
  980. * $(TABLE_SV
  981. * $(SVH x, asinh(x) )
  982. * $(SV $(NAN), $(NAN) )
  983. * $(SV $(PLUSMN)0, $(PLUSMN)0 )
  984. * $(SV $(PLUSMN)$(INFIN),$(PLUSMN)$(INFIN))
  985. * )
  986. */
  987. real asinh(real x) @safe pure nothrow
  988. {
  989. return (fabs(x) > 1 / real.epsilon)
  990. // beyond this point, x*x + 1 == x*x
  991. ? copysign(LN2 + log(fabs(x)), x)
  992. // sqrt(x*x + 1) == 1 + x * x / ( 1 + sqrt(x*x + 1) )
  993. : copysign(log1p(fabs(x) + x*x / (1 + sqrt(x*x + 1)) ), x);
  994. }
  995. /// ditto
  996. double asinh(double x) @safe pure nothrow { return asinh(cast(real)x); }
  997. /// ditto
  998. float asinh(float x) @safe pure nothrow { return asinh(cast(real)x); }
  999. unittest
  1000. {
  1001. assert(isIdentical(asinh(0.0), 0.0));
  1002. assert(isIdentical(asinh(-0.0), -0.0));
  1003. assert(asinh(real.infinity) == real.infinity);
  1004. assert(asinh(-real.infinity) == -real.infinity);
  1005. assert(isNaN(asinh(real.nan)));
  1006. assert(equalsDigit(asinh(sinh(3.0)), 3, useDigits));
  1007. }
  1008. /***********************************
  1009. * Calculates the inverse hyperbolic tangent of x,
  1010. * returning a value from ranging from -1 to 1.
  1011. *
  1012. * Mathematically, atanh(x) = log( (1+x)/(1-x) ) / 2
  1013. *
  1014. *
  1015. * $(TABLE_DOMRG
  1016. * $(DOMAIN -$(INFIN)..$(INFIN))
  1017. * $(RANGE -1..1) )
  1018. * $(TABLE_SV
  1019. * $(SVH x, acosh(x) )
  1020. * $(SV $(NAN), $(NAN) )
  1021. * $(SV $(PLUSMN)0, $(PLUSMN)0)
  1022. * $(SV -$(INFIN), -0)
  1023. * )
  1024. */
  1025. real atanh(real x) @safe pure nothrow
  1026. {
  1027. // log( (1+x)/(1-x) ) == log ( 1 + (2*x)/(1-x) )
  1028. return 0.5 * log1p( 2 * x / (1 - x) );
  1029. }
  1030. /// ditto
  1031. double atanh(double x) @safe pure nothrow { return atanh(cast(real)x); }
  1032. /// ditto
  1033. float atanh(float x) @safe pure nothrow { return atanh(cast(real)x); }
  1034. unittest
  1035. {
  1036. assert(isIdentical(atanh(0.0), 0.0));
  1037. assert(isIdentical(atanh(-0.0),-0.0));
  1038. assert(isNaN(atanh(real.nan)));
  1039. assert(isNaN(atanh(-real.infinity)));
  1040. assert(atanh(0.0) == 0);
  1041. assert(equalsDigit(atanh(tanh(0.5L)), 0.5, useDigits));
  1042. }
  1043. /*****************************************
  1044. * Returns x rounded to a long value using the current rounding mode.
  1045. * If the integer value of x is
  1046. * greater than long.max, the result is
  1047. * indeterminate.
  1048. */
  1049. long rndtol(real x) @safe pure nothrow; /* intrinsic */
  1050. /*****************************************
  1051. * Returns x rounded to a long value using the FE_TONEAREST rounding mode.
  1052. * If the integer value of x is
  1053. * greater than long.max, the result is
  1054. * indeterminate.
  1055. */
  1056. extern (C) real rndtonl(real x);
  1057. /***************************************
  1058. * Compute square root of x.
  1059. *
  1060. * $(TABLE_SV
  1061. * $(TR $(TH x) $(TH sqrt(x)) $(TH invalid?))
  1062. * $(TR $(TD -0.0) $(TD -0.0) $(TD no))
  1063. * $(TR $(TD $(LT)0.0) $(TD $(NAN)) $(TD yes))
  1064. * $(TR $(TD +$(INFIN)) $(TD +$(INFIN)) $(TD no))
  1065. * )
  1066. */
  1067. float sqrt(float x) @safe pure nothrow; /* intrinsic */
  1068. /// ditto
  1069. double sqrt(double x) @safe pure nothrow; /* intrinsic */
  1070. /// ditto
  1071. real sqrt(real x) @safe pure nothrow; /* intrinsic */
  1072. unittest
  1073. {
  1074. //ctfe
  1075. enum ZX80 = sqrt(7.0f);
  1076. enum ZX81 = sqrt(7.0);
  1077. enum ZX82 = sqrt(7.0L);
  1078. }
  1079. creal sqrt(creal z) @safe pure nothrow
  1080. {
  1081. creal c;
  1082. real x,y,w,r;
  1083. if (z == 0)
  1084. {
  1085. c = 0 + 0i;
  1086. }
  1087. else
  1088. {
  1089. real z_re = z.re;
  1090. real z_im = z.im;
  1091. x = fabs(z_re);
  1092. y = fabs(z_im);
  1093. if (x >= y)
  1094. {
  1095. r = y / x;
  1096. w = sqrt(x) * sqrt(0.5 * (1 + sqrt(1 + r * r)));
  1097. }
  1098. else
  1099. {
  1100. r = x / y;
  1101. w = sqrt(y) * sqrt(0.5 * (r + sqrt(1 + r * r)));
  1102. }
  1103. if (z_re >= 0)
  1104. {
  1105. c = w + (z_im / (w + w)) * 1.0i;
  1106. }
  1107. else
  1108. {
  1109. if (z_im < 0)
  1110. w = -w;
  1111. c = z_im / (w + w) + w * 1.0i;
  1112. }
  1113. }
  1114. return c;
  1115. }
  1116. /**
  1117. * Calculates e$(SUP x).
  1118. *
  1119. * $(TABLE_SV
  1120. * $(TR $(TH x) $(TH e$(SUP x)) )
  1121. * $(TR $(TD +$(INFIN)) $(TD +$(INFIN)) )
  1122. * $(TR $(TD -$(INFIN)) $(TD +0.0) )
  1123. * $(TR $(TD $(NAN)) $(TD $(NAN)) )
  1124. * )
  1125. */
  1126. real exp(real x) @trusted pure nothrow
  1127. {
  1128. version(D_InlineAsm_X86)
  1129. {
  1130. // e^^x = 2^^(LOG2E*x)
  1131. // (This is valid because the overflow & underflow limits for exp
  1132. // and exp2 are so similar).
  1133. return exp2(LOG2E*x);
  1134. }
  1135. else version(D_InlineAsm_X86_64)
  1136. {
  1137. // e^^x = 2^^(LOG2E*x)
  1138. // (This is valid because the overflow & underflow limits for exp
  1139. // and exp2 are so similar).
  1140. return exp2(LOG2E*x);
  1141. }
  1142. else
  1143. {
  1144. // Coefficients for exp(x)
  1145. static immutable real[3] P = [
  1146. 9.9999999999999999991025E-1L,
  1147. 3.0299440770744196129956E-2L,
  1148. 1.2617719307481059087798E-4L,
  1149. ];
  1150. static immutable real[4] Q = [
  1151. 2.0000000000000000000897E0L,
  1152. 2.2726554820815502876593E-1L,
  1153. 2.5244834034968410419224E-3L,
  1154. 3.0019850513866445504159E-6L,
  1155. ];
  1156. // C1 + C2 = LN2.
  1157. enum real C1 = 6.9314575195312500000000E-1L;
  1158. enum real C2 = 1.428606820309417232121458176568075500134E-6L;
  1159. // Overflow and Underflow limits.
  1160. enum real OF = 1.1356523406294143949492E4L;
  1161. enum real UF = -1.1432769596155737933527E4L;
  1162. // Special cases.
  1163. if (isNaN(x))
  1164. return x;
  1165. if (x > OF)
  1166. return real.infinity;
  1167. if (x < UF)
  1168. return 0.0;
  1169. // Express: e^^x = e^^g * 2^^n
  1170. // = e^^g * e^^(n * LOG2E)
  1171. // = e^^(g + n * LOG2E)
  1172. int n = cast(int)floor(LOG2E * x + 0.5);
  1173. x -= n * C1;
  1174. x -= n * C2;
  1175. // Rational approximation for exponential of the fractional part:
  1176. // e^^x = 1 + 2x P(x^^2) / (Q(x^^2) - P(x^^2))
  1177. real xx = x * x;
  1178. real px = x * poly(xx, P);
  1179. x = px / (poly(xx, Q) - px);
  1180. x = 1.0 + ldexp(x, 1);
  1181. // Scale by power of 2.
  1182. x = ldexp(x, n);
  1183. return x;
  1184. }
  1185. }
  1186. /// ditto
  1187. double exp(double x) @safe pure nothrow { return exp(cast(real)x); }
  1188. /// ditto
  1189. float exp(float x) @safe pure nothrow { return exp(cast(real)x); }
  1190. unittest
  1191. {
  1192. assert(equalsDigit(exp(3.0L), E * E * E, useDigits));
  1193. }
  1194. /**
  1195. * Calculates the value of the natural logarithm base (e)
  1196. * raised to the power of x, minus 1.
  1197. *
  1198. * For very small x, expm1(x) is more accurate
  1199. * than exp(x)-1.
  1200. *
  1201. * $(TABLE_SV
  1202. * $(TR $(TH x) $(TH e$(SUP x)-1) )
  1203. * $(TR $(TD $(PLUSMN)0.0) $(TD $(PLUSMN)0.0) )
  1204. * $(TR $(TD +$(INFIN)) $(TD +$(INFIN)) )
  1205. * $(TR $(TD -$(INFIN)) $(TD -1.0) )
  1206. * $(TR $(TD $(NAN)) $(TD $(NAN)) )
  1207. * )
  1208. */
  1209. real expm1(real x) @trusted pure nothrow
  1210. {
  1211. version(D_InlineAsm_X86)
  1212. {
  1213. enum PARAMSIZE = (real.sizeof+3)&(0xFFFF_FFFC); // always a multiple of 4
  1214. asm
  1215. {
  1216. /* expm1() for x87 80-bit reals, IEEE754-2008 conformant.
  1217. * Author: Don Clugston.
  1218. *
  1219. * expm1(x) = 2^^(rndint(y))* 2^^(y-rndint(y)) - 1 where y = LN2*x.
  1220. * = 2rndy * 2ym1 + 2rndy - 1, where 2rndy = 2^^(rndint(y))
  1221. * and 2ym1 = (2^^(y-rndint(y))-1).
  1222. * If 2rndy < 0.5*real.epsilon, result is -1.
  1223. * Implementation is otherwise the same as for exp2()
  1224. */
  1225. naked;
  1226. fld real ptr [ESP+4] ; // x
  1227. mov AX, [ESP+4+8]; // AX = exponent and sign
  1228. sub ESP, 12+8; // Create scratch space on the stack
  1229. // [ESP,ESP+2] = scratchint
  1230. // [ESP+4..+6, +8..+10, +10] = scratchreal
  1231. // set scratchreal mantissa = 1.0
  1232. mov dword ptr [ESP+8], 0;
  1233. mov dword ptr [ESP+8+4], 0x80000000;
  1234. and AX, 0x7FFF; // drop sign bit
  1235. cmp AX, 0x401D; // avoid InvalidException in fist
  1236. jae L_extreme;
  1237. fldl2e;
  1238. fmulp ST(1), ST; // y = x*log2(e)
  1239. fist dword ptr [ESP]; // scratchint = rndint(y)
  1240. fisub dword ptr [ESP]; // y - rndint(y)
  1241. // and now set scratchreal exponent
  1242. mov EAX, [ESP];
  1243. add EAX, 0x3fff;
  1244. jle short L_largenegative;
  1245. cmp EAX,0x8000;
  1246. jge short L_largepositive;
  1247. mov [ESP+8+8],AX;
  1248. f2xm1; // 2ym1 = 2^^(y-rndint(y)) -1
  1249. fld real ptr [ESP+8] ; // 2rndy = 2^^rndint(y)
  1250. fmul ST(1), ST; // ST=2rndy, ST(1)=2rndy*2ym1
  1251. fld1;
  1252. fsubp ST(1), ST; // ST = 2rndy-1, ST(1) = 2rndy * 2ym1 - 1
  1253. faddp ST(1), ST; // ST = 2rndy * 2ym1 + 2rndy - 1
  1254. add ESP,12+8;
  1255. ret PARAMSIZE;
  1256. L_extreme: // Extreme exponent. X is very large positive, very
  1257. // large negative, infinity, or NaN.
  1258. fxam;
  1259. fstsw AX;
  1260. test AX, 0x0400; // NaN_or_zero, but we already know x!=0
  1261. jz L_was_nan; // if x is NaN, returns x
  1262. test AX, 0x0200;
  1263. jnz L_largenegative;
  1264. L_largepositive:
  1265. // Set scratchreal = real.max.
  1266. // squaring it will create infinity, and set overflow flag.
  1267. mov word ptr [ESP+8+8], 0x7FFE;
  1268. fstp ST(0);
  1269. fld real ptr [ESP+8]; // load scratchreal
  1270. fmul ST(0), ST; // square it, to create havoc!
  1271. L_was_nan:
  1272. add ESP,12+8;
  1273. ret PARAMSIZE;
  1274. L_largenegative:
  1275. fstp ST(0);
  1276. fld1;
  1277. fchs; // return -1. Underflow flag is not set.
  1278. add ESP,12+8;
  1279. ret PARAMSIZE;
  1280. }
  1281. }
  1282. else version(D_InlineAsm_X86_64)
  1283. {
  1284. asm
  1285. {
  1286. naked;
  1287. }
  1288. version (Win64)
  1289. {
  1290. asm
  1291. {
  1292. fld real ptr [RCX]; // x
  1293. mov AX,[RCX+8]; // AX = exponent and sign
  1294. }
  1295. }
  1296. else
  1297. {
  1298. asm
  1299. {
  1300. fld real ptr [RSP+8]; // x
  1301. mov AX,[RSP+8+8]; // AX = exponent and sign
  1302. }
  1303. }
  1304. asm
  1305. {
  1306. /* expm1() for x87 80-bit reals, IEEE754-2008 conformant.
  1307. * Author: Don Clugston.
  1308. *
  1309. * expm1(x) = 2^(rndint(y))* 2^(y-rndint(y)) - 1 where y = LN2*x.
  1310. * = 2rndy * 2ym1 + 2rndy - 1, where 2rndy = 2^(rndint(y))
  1311. * and 2ym1 = (2^(y-rndint(y))-1).
  1312. * If 2rndy < 0.5*real.epsilon, result is -1.
  1313. * Implementation is otherwise the same as for exp2()
  1314. */
  1315. sub RSP, 24; // Create scratch space on the stack
  1316. // [RSP,RSP+2] = scratchint
  1317. // [RSP+4..+6, +8..+10, +10] = scratchreal
  1318. // set scratchreal mantissa = 1.0
  1319. mov dword ptr [RSP+8], 0;
  1320. mov dword ptr [RSP+8+4], 0x80000000;
  1321. and AX, 0x7FFF; // drop sign bit
  1322. cmp AX, 0x401D; // avoid InvalidException in fist
  1323. jae L_extreme;
  1324. fldl2e;
  1325. fmul ; // y = x*log2(e)
  1326. fist dword ptr [RSP]; // scratchint = rndint(y)
  1327. fisub dword ptr [RSP]; // y - rndint(y)
  1328. // and now set scratchreal exponent
  1329. mov EAX, [RSP];
  1330. add EAX, 0x3fff;
  1331. jle short L_largenegative;
  1332. cmp EAX,0x8000;
  1333. jge short L_largepositive;
  1334. mov [RSP+8+8],AX;
  1335. f2xm1; // 2^(y-rndint(y)) -1
  1336. fld real ptr [RSP+8] ; // 2^rndint(y)
  1337. fmul ST(1), ST;
  1338. fld1;
  1339. fsubp ST(1), ST;
  1340. fadd;
  1341. add RSP,24;
  1342. ret;
  1343. L_extreme: // Extreme exponent. X is very large positive, very
  1344. // large negative, infinity, or NaN.
  1345. fxam;
  1346. fstsw AX;
  1347. test AX, 0x0400; // NaN_or_zero, but we already know x!=0
  1348. jz L_was_nan; // if x is NaN, returns x
  1349. test AX, 0x0200;
  1350. jnz L_largenegative;
  1351. L_largepositive:
  1352. // Set scratchreal = real.max.
  1353. // squaring it will create infinity, and set overflow flag.
  1354. mov word ptr [RSP+8+8], 0x7FFE;
  1355. fstp ST(0);
  1356. fld real ptr [RSP+8]; // load scratchreal
  1357. fmul ST(0), ST; // square it, to create havoc!
  1358. L_was_nan:
  1359. add RSP,24;
  1360. ret;
  1361. L_largenegative:
  1362. fstp ST(0);
  1363. fld1;
  1364. fchs; // return -1. Underflow flag is not set.
  1365. add RSP,24;
  1366. ret;
  1367. }
  1368. }
  1369. else
  1370. {
  1371. // Coefficients for exp(x) - 1
  1372. static immutable real[5] P = [
  1373. -1.586135578666346600772998894928250240826E4L,
  1374. 2.642771505685952966904660652518429479531E3L,
  1375. -3.423199068835684263987132888286791620673E2L,
  1376. 1.800826371455042224581246202420972737840E1L,
  1377. -5.238523121205561042771939008061958820811E-1L,
  1378. ];
  1379. static immutable real[6] Q = [
  1380. -9.516813471998079611319047060563358064497E4L,
  1381. 3.964866271411091674556850458227710004570E4L,
  1382. -7.207678383830091850230366618190187434796E3L,
  1383. 7.206038318724600171970199625081491823079E2L,
  1384. -4.002027679107076077238836622982900945173E1L,
  1385. 1.000000000000000000000000000000000000000E0L,
  1386. ];
  1387. // C1 + C2 = LN2.
  1388. enum real C1 = 6.9314575195312500000000E-1L;
  1389. enum real C2 = 1.4286068203094172321215E-6L;
  1390. // Overflow and Underflow limits.
  1391. enum real OF = 1.1356523406294143949492E4L;
  1392. enum real UF = -4.5054566736396445112120088E1L;
  1393. // Special cases.
  1394. if (x > OF)
  1395. return real.infinity;
  1396. if (x == 0.0)
  1397. return x;
  1398. if (x < UF)
  1399. return -1.0;
  1400. // Express x = LN2 (n + remainder), remainder not exceeding 1/2.
  1401. int n = cast(int)floor(0.5 + x / LN2);
  1402. x -= n * C1;
  1403. x -= n * C2;
  1404. // Rational approximation:
  1405. // exp(x) - 1 = x + 0.5 x^^2 + x^^3 P(x) / Q(x)
  1406. real px = x * poly(x, P);
  1407. real qx = poly(x, Q);
  1408. real xx = x * x;
  1409. qx = x + (0.5 * xx + xx * px / qx);
  1410. // We have qx = exp(remainder LN2) - 1, so:
  1411. // exp(x) - 1 = 2^^n (qx + 1) - 1 = 2^^n qx + 2^^n - 1.
  1412. px = ldexp(1.0, n);
  1413. x = px * qx + (px - 1.0);
  1414. return x;
  1415. }
  1416. }
  1417. /**
  1418. * Calculates 2$(SUP x).
  1419. *
  1420. * $(TABLE_SV
  1421. * $(TR $(TH x) $(TH exp2(x)) )
  1422. * $(TR $(TD +$(INFIN)) $(TD +$(INFIN)) )
  1423. * $(TR $(TD -$(INFIN)) $(TD +0.0) )
  1424. * $(TR $(TD $(NAN)) $(TD $(NAN)) )
  1425. * )
  1426. */
  1427. real exp2(real x) @trusted pure nothrow
  1428. {
  1429. version(D_InlineAsm_X86)
  1430. {
  1431. enum PARAMSIZE = (real.sizeof+3)&(0xFFFF_FFFC); // always a multiple of 4
  1432. asm
  1433. {
  1434. /* exp2() for x87 80-bit reals, IEEE754-2008 conformant.
  1435. * Author: Don Clugston.
  1436. *
  1437. * exp2(x) = 2^^(rndint(x))* 2^^(y-rndint(x))
  1438. * The trick for high performance is to avoid the fscale(28cycles on core2),
  1439. * frndint(19 cycles), leaving f2xm1(19 cycles) as the only slow instruction.
  1440. *
  1441. * We can do frndint by using fist. BUT we can't use it for huge numbers,
  1442. * because it will set the Invalid Operation flag if overflow or NaN occurs.
  1443. * Fortunately, whenever this happens the result would be zero or infinity.
  1444. *
  1445. * We can perform fscale by directly poking into the exponent. BUT this doesn't
  1446. * work for the (very rare) cases where the result is subnormal. So we fall back
  1447. * to the slow method in that case.
  1448. */
  1449. naked;
  1450. fld real ptr [ESP+4] ; // x
  1451. mov AX, [ESP+4+8]; // AX = exponent and sign
  1452. sub ESP, 12+8; // Create scratch space on the stack
  1453. // [ESP,ESP+2] = scratchint
  1454. // [ESP+4..+6, +8..+10, +10] = scratchreal
  1455. // set scratchreal mantissa = 1.0
  1456. mov dword ptr [ESP+8], 0;
  1457. mov dword ptr [ESP+8+4], 0x80000000;
  1458. and AX, 0x7FFF; // drop sign bit
  1459. cmp AX, 0x401D; // avoid InvalidException in fist
  1460. jae L_extreme;
  1461. fist dword ptr [ESP]; // scratchint = rndint(x)
  1462. fisub dword ptr [ESP]; // x - rndint(x)
  1463. // and now set scratchreal exponent
  1464. mov EAX, [ESP];
  1465. add EAX, 0x3fff;
  1466. jle short L_subnormal;
  1467. cmp EAX,0x8000;
  1468. jge short L_overflow;
  1469. mov [ESP+8+8],AX;
  1470. L_normal:
  1471. f2xm1;
  1472. fld1;
  1473. faddp ST(1), ST; // 2^^(x-rndint(x))
  1474. fld real ptr [ESP+8] ; // 2^^rndint(x)
  1475. add ESP,12+8;
  1476. fmulp ST(1), ST;
  1477. ret PARAMSIZE;
  1478. L_subnormal:
  1479. // Result will be subnormal.
  1480. // In this rare case, the simple poking method doesn't work.
  1481. // The speed doesn't matter, so use the slow fscale method.
  1482. fild dword ptr [ESP]; // scratchint
  1483. fld1;
  1484. fscale;
  1485. fstp real ptr [ESP+8]; // scratchreal = 2^^scratchint
  1486. fstp ST(0); // drop scratchint
  1487. jmp L_normal;
  1488. L_extreme: // Extreme exponent. X is very large positive, very
  1489. // large negative, infinity, or NaN.
  1490. fxam;
  1491. fstsw AX;
  1492. test AX, 0x0400; // NaN_or_zero, but we already know x!=0
  1493. jz L_was_nan; // if x is NaN, returns x
  1494. // set scratchreal = real.min_normal
  1495. // squaring it will return 0, setting underflow flag
  1496. mov word ptr [ESP+8+8], 1;
  1497. test AX, 0x0200;
  1498. jnz L_waslargenegative;
  1499. L_overflow:
  1500. // Set scratchreal = real.max.
  1501. // squaring it will create infinity, and set overflow flag.
  1502. mov word ptr [ESP+8+8], 0x7FFE;
  1503. L_waslargenegative:
  1504. fstp ST(0);
  1505. fld real ptr [ESP+8]; // load scratchreal
  1506. fmul ST(0), ST; // square it, to create havoc!
  1507. L_was_nan:
  1508. add ESP,12+8;
  1509. ret PARAMSIZE;
  1510. }
  1511. }
  1512. else version(D_InlineAsm_X86_64)
  1513. {
  1514. asm
  1515. {
  1516. naked;
  1517. }
  1518. version (Win64)
  1519. {
  1520. asm
  1521. {
  1522. fld real ptr [RCX]; // x
  1523. mov AX,[RCX+8]; // AX = exponent and sign
  1524. }
  1525. }
  1526. else
  1527. {
  1528. asm
  1529. {
  1530. fld real ptr [RSP+8]; // x
  1531. mov AX,[RSP+8+8]; // AX = exponent and sign
  1532. }
  1533. }
  1534. asm
  1535. {
  1536. /* exp2() for x87 80-bit reals, IEEE754-2008 conformant.
  1537. * Author: Don Clugston.
  1538. *
  1539. * exp2(x) = 2^(rndint(x))* 2^(y-rndint(x))
  1540. * The trick for high performance is to avoid the fscale(28cycles on core2),
  1541. * frndint(19 cycles), leaving f2xm1(19 cycles) as the only slow instruction.
  1542. *
  1543. * We can do frndint by using fist. BUT we can't use it for huge numbers,
  1544. * because it will set the Invalid Operation flag is overflow or NaN occurs.
  1545. * Fortunately, whenever this happens the result would be zero or infinity.
  1546. *
  1547. * We can perform fscale by directly poking into the exponent. BUT this doesn't
  1548. * work f…