Number.Grisu3.cs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729
  1. // Licensed to the .NET Foundation under one or more agreements.
  2. // The .NET Foundation licenses this file to you under the MIT license.
  3. // See the LICENSE file in the project root for more information.
  4. using System.Diagnostics;
  5. namespace System
  6. {
  7. internal static partial class Number
  8. {
  9. internal static unsafe class Grisu3
  10. {
  11. private const int Alpha = -59;
  12. private const double D1Log210 = 0.301029995663981195;
  13. private const int Gamma = -32;
  14. private const int PowerDecimalExponentDistance = 8;
  15. private const int PowerMinDecimalExponent = -348;
  16. private const int PowerMaxDecimalExponent = 340;
  17. private const int PowerOffset = -PowerMinDecimalExponent;
  18. private const uint Ten4 = 10000;
  19. private const uint Ten5 = 100000;
  20. private const uint Ten6 = 1000000;
  21. private const uint Ten7 = 10000000;
  22. private const uint Ten8 = 100000000;
  23. private const uint Ten9 = 1000000000;
  24. private static readonly short[] s_CachedPowerBinaryExponents = new short[]
  25. {
  26. -1220,
  27. -1193,
  28. -1166,
  29. -1140,
  30. -1113,
  31. -1087,
  32. -1060,
  33. -1034,
  34. -1007,
  35. -980,
  36. -954,
  37. -927,
  38. -901,
  39. -874,
  40. -847,
  41. -821,
  42. -794,
  43. -768,
  44. -741,
  45. -715,
  46. -688,
  47. -661,
  48. -635,
  49. -608,
  50. -582,
  51. -555,
  52. -529,
  53. -502,
  54. -475,
  55. -449,
  56. -422,
  57. -396,
  58. -369,
  59. -343,
  60. -316,
  61. -289,
  62. -263,
  63. -236,
  64. -210,
  65. -183,
  66. -157,
  67. -130,
  68. -103,
  69. -77,
  70. -50,
  71. -24,
  72. 3,
  73. 30,
  74. 56,
  75. 83,
  76. 109,
  77. 136,
  78. 162,
  79. 189,
  80. 216,
  81. 242,
  82. 269,
  83. 295,
  84. 322,
  85. 348,
  86. 375,
  87. 402,
  88. 428,
  89. 455,
  90. 481,
  91. 508,
  92. 534,
  93. 561,
  94. 588,
  95. 614,
  96. 641,
  97. 667,
  98. 694,
  99. 720,
  100. 747,
  101. 774,
  102. 800,
  103. 827,
  104. 853,
  105. 880,
  106. 907,
  107. 933,
  108. 960,
  109. 986,
  110. 1013,
  111. 1039,
  112. 1066,
  113. };
  114. private static readonly short[] s_CachedPowerDecimalExponents = new short[]
  115. {
  116. PowerMinDecimalExponent,
  117. -340,
  118. -332,
  119. -324,
  120. -316,
  121. -308,
  122. -300,
  123. -292,
  124. -284,
  125. -276,
  126. -268,
  127. -260,
  128. -252,
  129. -244,
  130. -236,
  131. -228,
  132. -220,
  133. -212,
  134. -204,
  135. -196,
  136. -188,
  137. -180,
  138. -172,
  139. -164,
  140. -156,
  141. -148,
  142. -140,
  143. -132,
  144. -124,
  145. -116,
  146. -108,
  147. -100,
  148. -92,
  149. -84,
  150. -76,
  151. -68,
  152. -60,
  153. -52,
  154. -44,
  155. -36,
  156. -28,
  157. -20,
  158. -12,
  159. -4,
  160. 4,
  161. 12,
  162. 20,
  163. 28,
  164. 36,
  165. 44,
  166. 52,
  167. 60,
  168. 68,
  169. 76,
  170. 84,
  171. 92,
  172. 100,
  173. 108,
  174. 116,
  175. 124,
  176. 132,
  177. 140,
  178. 148,
  179. 156,
  180. 164,
  181. 172,
  182. 180,
  183. 188,
  184. 196,
  185. 204,
  186. 212,
  187. 220,
  188. 228,
  189. 236,
  190. 244,
  191. 252,
  192. 260,
  193. 268,
  194. 276,
  195. 284,
  196. 292,
  197. 300,
  198. 308,
  199. 316,
  200. 324,
  201. 332,
  202. PowerMaxDecimalExponent,
  203. };
  204. private static readonly uint[] s_CachedPowerOfTen = new uint[]
  205. {
  206. 1, // 10^0
  207. 10, // 10^1
  208. 100, // 10^2
  209. 1000, // 10^3
  210. 10000, // 10^4
  211. 100000, // 10^5
  212. 1000000, // 10^6
  213. 10000000, // 10^7
  214. 100000000, // 10^8
  215. 1000000000, // 10^9
  216. };
  217. private static readonly ulong[] s_CachedPowerSignificands = new ulong[]
  218. {
  219. 0xFA8FD5A0081C0288,
  220. 0xBAAEE17FA23EBF76,
  221. 0x8B16FB203055AC76,
  222. 0xCF42894A5DCE35EA,
  223. 0x9A6BB0AA55653B2D,
  224. 0xE61ACF033D1A45DF,
  225. 0xAB70FE17C79AC6CA,
  226. 0xFF77B1FCBEBCDC4F,
  227. 0xBE5691EF416BD60C,
  228. 0x8DD01FAD907FFC3C,
  229. 0xD3515C2831559A83,
  230. 0x9D71AC8FADA6C9B5,
  231. 0xEA9C227723EE8BCB,
  232. 0xAECC49914078536D,
  233. 0x823C12795DB6CE57,
  234. 0xC21094364DFB5637,
  235. 0x9096EA6F3848984F,
  236. 0xD77485CB25823AC7,
  237. 0xA086CFCD97BF97F4,
  238. 0xEF340A98172AACE5,
  239. 0xB23867FB2A35B28E,
  240. 0x84C8D4DFD2C63F3B,
  241. 0xC5DD44271AD3CDBA,
  242. 0x936B9FCEBB25C996,
  243. 0xDBAC6C247D62A584,
  244. 0xA3AB66580D5FDAF6,
  245. 0xF3E2F893DEC3F126,
  246. 0xB5B5ADA8AAFF80B8,
  247. 0x87625F056C7C4A8B,
  248. 0xC9BCFF6034C13053,
  249. 0x964E858C91BA2655,
  250. 0xDFF9772470297EBD,
  251. 0xA6DFBD9FB8E5B88F,
  252. 0xF8A95FCF88747D94,
  253. 0xB94470938FA89BCF,
  254. 0x8A08F0F8BF0F156B,
  255. 0xCDB02555653131B6,
  256. 0x993FE2C6D07B7FAC,
  257. 0xE45C10C42A2B3B06,
  258. 0xAA242499697392D3,
  259. 0xFD87B5F28300CA0E,
  260. 0xBCE5086492111AEB,
  261. 0x8CBCCC096F5088CC,
  262. 0xD1B71758E219652C,
  263. 0x9C40000000000000,
  264. 0xE8D4A51000000000,
  265. 0xAD78EBC5AC620000,
  266. 0x813F3978F8940984,
  267. 0xC097CE7BC90715B3,
  268. 0x8F7E32CE7BEA5C70,
  269. 0xD5D238A4ABE98068,
  270. 0x9F4F2726179A2245,
  271. 0xED63A231D4C4FB27,
  272. 0xB0DE65388CC8ADA8,
  273. 0x83C7088E1AAB65DB,
  274. 0xC45D1DF942711D9A,
  275. 0x924D692CA61BE758,
  276. 0xDA01EE641A708DEA,
  277. 0xA26DA3999AEF774A,
  278. 0xF209787BB47D6B85,
  279. 0xB454E4A179DD1877,
  280. 0x865B86925B9BC5C2,
  281. 0xC83553C5C8965D3D,
  282. 0x952AB45CFA97A0B3,
  283. 0xDE469FBD99A05FE3,
  284. 0xA59BC234DB398C25,
  285. 0xF6C69A72A3989F5C,
  286. 0xB7DCBF5354E9BECE,
  287. 0x88FCF317F22241E2,
  288. 0xCC20CE9BD35C78A5,
  289. 0x98165AF37B2153DF,
  290. 0xE2A0B5DC971F303A,
  291. 0xA8D9D1535CE3B396,
  292. 0xFB9B7CD9A4A7443C,
  293. 0xBB764C4CA7A44410,
  294. 0x8BAB8EEFB6409C1A,
  295. 0xD01FEF10A657842C,
  296. 0x9B10A4E5E9913129,
  297. 0xE7109BFBA19C0C9D,
  298. 0xAC2820D9623BF429,
  299. 0x80444B5E7AA7CF85,
  300. 0xBF21E44003ACDD2D,
  301. 0x8E679C2F5E44FF8F,
  302. 0xD433179D9C8CB841,
  303. 0x9E19DB92B4E31BA9,
  304. 0xEB96BF6EBADF77D9,
  305. 0xAF87023B9BF0EE6B,
  306. };
  307. public static bool Run(double value, int precision, ref NumberBuffer number)
  308. {
  309. // ========================================================================================================================================
  310. // This implementation is based on the paper: http://www.cs.tufts.edu/~nr/cs257/archive/florian-loitsch/printf.pdf
  311. // You must read this paper to fully understand the code.
  312. //
  313. // Deviation: Instead of generating shortest digits, we generate the digits according to the input count.
  314. // Therefore, we do not need m+ and m- which are used to determine the exact range of values.
  315. // ========================================================================================================================================
  316. //
  317. // Overview:
  318. //
  319. // The idea of Grisu3 is to leverage additional bits and cached power of ten to produce the digits.
  320. // We need to create a handmade floating point data structure DiyFp to extend the bits of double.
  321. // We also need to cache the powers of ten for digits generation. By choosing the correct index of powers
  322. // we need to start with, we can eliminate the expensive big num divide operation.
  323. //
  324. // Grisu3 is imprecision for some numbers. Fortunately, the algorithm itself can determine that and give us
  325. // a success/fail flag. We may fall back to other algorithms (For instance, Dragon4) if it fails.
  326. //
  327. // w: the normalized DiyFp from the input value.
  328. // mk: The index of the cached powers.
  329. // cmk: The cached power.
  330. // D: Product: w * cmk.
  331. // kappa: A factor used for generating digits. See step 5 of the Grisu3 procedure in the paper.
  332. // Handle sign bit.
  333. if (double.IsNegative(value))
  334. {
  335. value = -value;
  336. number.IsNegative = true;
  337. }
  338. else
  339. {
  340. number.IsNegative = false;
  341. }
  342. // Step 1: Determine the normalized DiyFp w.
  343. DiyFp.GenerateNormalizedDiyFp(value, out DiyFp w);
  344. // Step 2: Find the cached power of ten.
  345. // Compute the proper index mk.
  346. int mk = KComp(w.e + DiyFp.SignificandLength);
  347. // Retrieve the cached power of ten.
  348. CachedPower(mk, out DiyFp cmk, out int decimalExponent);
  349. // Step 3: Scale the w with the cached power of ten.
  350. DiyFp.Multiply(ref w, ref cmk, out DiyFp D);
  351. // Step 4: Generate digits.
  352. bool isSuccess = DigitGen(ref D, precision, number.GetDigitsPointer(), out int length, out int kappa);
  353. if (isSuccess)
  354. {
  355. number.Digits[precision] = (byte)('\0');
  356. number.Scale = (length - decimalExponent + kappa);
  357. }
  358. return isSuccess;
  359. }
  360. // Returns the biggest power of ten that is less than or equal to the given number.
  361. static void BiggestPowerTenLessThanOrEqualTo(uint number, int bits, out uint power, out int exponent)
  362. {
  363. switch (bits)
  364. {
  365. case 32:
  366. case 31:
  367. case 30:
  368. {
  369. if (Ten9 <= number)
  370. {
  371. power = Ten9;
  372. exponent = 9;
  373. break;
  374. }
  375. goto case 29;
  376. }
  377. case 29:
  378. case 28:
  379. case 27:
  380. {
  381. if (Ten8 <= number)
  382. {
  383. power = Ten8;
  384. exponent = 8;
  385. break;
  386. }
  387. goto case 26;
  388. }
  389. case 26:
  390. case 25:
  391. case 24:
  392. {
  393. if (Ten7 <= number)
  394. {
  395. power = Ten7;
  396. exponent = 7;
  397. break;
  398. }
  399. goto case 23;
  400. }
  401. case 23:
  402. case 22:
  403. case 21:
  404. case 20:
  405. {
  406. if (Ten6 <= number)
  407. {
  408. power = Ten6;
  409. exponent = 6;
  410. break;
  411. }
  412. goto case 19;
  413. }
  414. case 19:
  415. case 18:
  416. case 17:
  417. {
  418. if (Ten5 <= number)
  419. {
  420. power = Ten5;
  421. exponent = 5;
  422. break;
  423. }
  424. goto case 16;
  425. }
  426. case 16:
  427. case 15:
  428. case 14:
  429. {
  430. if (Ten4 <= number)
  431. {
  432. power = Ten4;
  433. exponent = 4;
  434. break;
  435. }
  436. goto case 13;
  437. }
  438. case 13:
  439. case 12:
  440. case 11:
  441. case 10:
  442. {
  443. if (1000 <= number)
  444. {
  445. power = 1000;
  446. exponent = 3;
  447. break;
  448. }
  449. goto case 9;
  450. }
  451. case 9:
  452. case 8:
  453. case 7:
  454. {
  455. if (100 <= number)
  456. {
  457. power = 100;
  458. exponent = 2;
  459. break;
  460. }
  461. goto case 6;
  462. }
  463. case 6:
  464. case 5:
  465. case 4:
  466. {
  467. if (10 <= number)
  468. {
  469. power = 10;
  470. exponent = 1;
  471. break;
  472. }
  473. goto case 3;
  474. }
  475. case 3:
  476. case 2:
  477. case 1:
  478. {
  479. if (1 <= number)
  480. {
  481. power = 1;
  482. exponent = 0;
  483. break;
  484. }
  485. goto case 0;
  486. }
  487. case 0:
  488. {
  489. power = 0;
  490. exponent = -1;
  491. break;
  492. }
  493. default:
  494. {
  495. power = 0;
  496. exponent = 0;
  497. Debug.Fail("unreachable");
  498. break;
  499. }
  500. }
  501. }
  502. private static void CachedPower(int k, out DiyFp cmk, out int decimalExponent)
  503. {
  504. int index = ((PowerOffset + k - 1) / PowerDecimalExponentDistance) + 1;
  505. cmk = new DiyFp(s_CachedPowerSignificands[index], s_CachedPowerBinaryExponents[index]);
  506. decimalExponent = s_CachedPowerDecimalExponents[index];
  507. }
  508. private static bool DigitGen(ref DiyFp mp, int precision, byte* digits, out int length, out int k)
  509. {
  510. // Split the input mp to two parts. Part 1 is integral. Part 2 can be used to calculate
  511. // fractional.
  512. //
  513. // mp: the input DiyFp scaled by cached power.
  514. // K: final kappa.
  515. // p1: part 1.
  516. // p2: part 2.
  517. Debug.Assert(precision > 0);
  518. Debug.Assert(digits != null);
  519. Debug.Assert(mp.e >= Alpha);
  520. Debug.Assert(mp.e <= Gamma);
  521. ulong mpF = mp.f;
  522. int mpE = mp.e;
  523. var one = new DiyFp(1UL << -mpE, mpE);
  524. ulong oneF = one.f;
  525. int oneNegE = -one.e;
  526. ulong ulp = 1;
  527. uint p1 = (uint)(mpF >> oneNegE);
  528. ulong p2 = mpF & (oneF - 1);
  529. // When p2 (fractional part) is zero, we can predicate if p1 is good to produce the numbers in requested digit count:
  530. //
  531. // - When requested digit count >= 11, p1 is not be able to exhaust the count as 10^(11 - 1) > uint.MaxValue >= p1.
  532. // - When p1 < 10^(count - 1), p1 is not be able to exhaust the count.
  533. // - Otherwise, p1 may have chance to exhaust the count.
  534. if ((p2 == 0) && ((precision >= 11) || (p1 < s_CachedPowerOfTen[precision - 1])))
  535. {
  536. length = 0;
  537. k = 0;
  538. return false;
  539. }
  540. // Note: The code in the paper simply assigns div to Ten9 and kappa to 10 directly.
  541. // That means we need to check if any leading zero of the generated
  542. // digits during the while loop, which hurts the performance.
  543. //
  544. // Now if we can estimate what the div and kappa, we do not need to check the leading zeros.
  545. // The idea is to find the biggest power of 10 that is less than or equal to the given number.
  546. // Then we don't need to worry about the leading zeros and we can get 10% performance gain.
  547. int index = 0;
  548. BiggestPowerTenLessThanOrEqualTo(p1, (DiyFp.SignificandLength - oneNegE), out uint div, out int kappa);
  549. kappa++;
  550. // Produce integral.
  551. while (kappa > 0)
  552. {
  553. int d = (int)(Math.DivRem(p1, div, out p1));
  554. digits[index] = (byte)('0' + d);
  555. index++;
  556. precision--;
  557. kappa--;
  558. if (precision == 0)
  559. {
  560. break;
  561. }
  562. div /= 10;
  563. }
  564. // End up here if we already exhausted the digit count.
  565. if (precision == 0)
  566. {
  567. ulong rest = ((ulong)(p1) << oneNegE) + p2;
  568. length = index;
  569. k = kappa;
  570. return RoundWeed(
  571. digits,
  572. index,
  573. rest,
  574. ((ulong)(div)) << oneNegE,
  575. ulp,
  576. ref k
  577. );
  578. }
  579. // We have to generate digits from part2 if we have requested digit count left
  580. // and part2 is greater than ulp.
  581. while ((precision > 0) && (p2 > ulp))
  582. {
  583. p2 *= 10;
  584. int d = (int)(p2 >> oneNegE);
  585. digits[index] = (byte)('0' + d);
  586. index++;
  587. precision--;
  588. kappa--;
  589. p2 &= (oneF - 1);
  590. ulp *= 10;
  591. }
  592. // If we haven't exhausted the requested digit counts, the Grisu3 algorithm fails.
  593. if (precision != 0)
  594. {
  595. length = 0;
  596. k = 0;
  597. return false;
  598. }
  599. length = index;
  600. k = kappa;
  601. return RoundWeed(digits, index, p2, oneF, ulp, ref k);
  602. }
  603. private static int KComp(int e)
  604. {
  605. return (int)(Math.Ceiling((Alpha - e + DiyFp.SignificandLength - 1) * D1Log210));
  606. }
  607. private static bool RoundWeed(byte* buffer, int len, ulong rest, ulong tenKappa, ulong ulp, ref int kappa)
  608. {
  609. Debug.Assert(rest < tenKappa);
  610. // 1. tenKappa <= ulp: we don't have an idea which way to round.
  611. // 2. Even if tenKappa > ulp, but if tenKappa <= 2 * ulp we cannot find the way to round.
  612. // Note: to prevent overflow, we need to use tenKappa - ulp <= ulp.
  613. if ((tenKappa <= ulp) || ((tenKappa - ulp) <= ulp))
  614. {
  615. return false;
  616. }
  617. // tenKappa >= 2 * (rest + ulp). We should round down.
  618. // Note: to prevent overflow, we need to check if tenKappa > 2 * rest as a prerequisite.
  619. if (((tenKappa - rest) > rest) && ((tenKappa - (2 * rest)) >= (2 * ulp)))
  620. {
  621. return true;
  622. }
  623. // tenKappa <= 2 * (rest - ulp). We should round up.
  624. // Note: to prevent overflow, we need to check if rest > ulp as a prerequisite.
  625. if ((rest > ulp) && (tenKappa <= (rest - ulp) || ((tenKappa - (rest - ulp)) <= (rest - ulp))))
  626. {
  627. // Find all 9s from end to start.
  628. buffer[len - 1]++;
  629. for (int i = len - 1; i > 0; i--)
  630. {
  631. if (buffer[i] != (byte)('0' + 10))
  632. {
  633. // We end up a number less than 9.
  634. break;
  635. }
  636. // Current number becomes 0 and add the promotion to the next number.
  637. buffer[i] = (byte)('0');
  638. buffer[i - 1]++;
  639. }
  640. if (buffer[0] == (char)('0' + 10))
  641. {
  642. // First number is '0' + 10 means all numbers are 9.
  643. // We simply make the first number to 1 and increase the kappa.
  644. buffer[0] = (byte)('1');
  645. kappa++;
  646. }
  647. return true;
  648. }
  649. return false;
  650. }
  651. }
  652. }
  653. }