test-dtoa.cc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507
  1. // Copyright 2010 the V8 project authors. All rights reserved.
  2. // Redistribution and use in source and binary forms, with or without
  3. // modification, are permitted provided that the following conditions are
  4. // met:
  5. //
  6. // * Redistributions of source code must retain the above copyright
  7. // notice, this list of conditions and the following disclaimer.
  8. // * Redistributions in binary form must reproduce the above
  9. // copyright notice, this list of conditions and the following
  10. // disclaimer in the documentation and/or other materials provided
  11. // with the distribution.
  12. // * Neither the name of Google Inc. nor the names of its
  13. // contributors may be used to endorse or promote products derived
  14. // from this software without specific prior written permission.
  15. //
  16. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  17. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  18. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  19. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  20. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  21. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  22. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  26. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. #include <stdlib.h>
  28. #include "double-conversion.h"
  29. #include "cctest.h"
  30. #include "gay-fixed.h"
  31. #include "gay-precision.h"
  32. #include "gay-shortest.h"
  33. #include "gay-shortest-single.h"
  34. #include "ieee.h"
  35. using namespace double_conversion;
  36. enum DtoaMode {
  37. SHORTEST,
  38. SHORTEST_SINGLE,
  39. FIXED,
  40. PRECISION
  41. };
  42. static void DoubleToAscii(double v, DtoaMode test_mode, int requested_digits,
  43. Vector<char> buffer, bool* sign, int* length,
  44. int* point) {
  45. DoubleToStringConverter::DtoaMode mode = DoubleToStringConverter::SHORTEST;
  46. switch (test_mode) {
  47. case SHORTEST: mode = DoubleToStringConverter::SHORTEST; break;
  48. case SHORTEST_SINGLE:
  49. mode = DoubleToStringConverter::SHORTEST_SINGLE;
  50. break;
  51. case FIXED: mode = DoubleToStringConverter::FIXED; break;
  52. case PRECISION: mode = DoubleToStringConverter::PRECISION; break;
  53. }
  54. DoubleToStringConverter::DoubleToAscii(v, mode, requested_digits,
  55. buffer.start(), buffer.length(),
  56. sign, length, point);
  57. }
  58. // Removes trailing '0' digits.
  59. static void TrimRepresentation(Vector<char> representation) {
  60. int len = strlen(representation.start());
  61. int i;
  62. for (i = len - 1; i >= 0; --i) {
  63. if (representation[i] != '0') break;
  64. }
  65. representation[i + 1] = '\0';
  66. }
  67. static const int kBufferSize = 100;
  68. TEST(DtoaVariousDoubles) {
  69. char buffer_container[kBufferSize];
  70. Vector<char> buffer(buffer_container, kBufferSize);
  71. int length;
  72. int point;
  73. bool sign;
  74. DoubleToAscii(0.0, SHORTEST, 0, buffer, &sign, &length, &point);
  75. CHECK_EQ("0", buffer.start());
  76. CHECK_EQ(1, point);
  77. DoubleToAscii(0.0f, SHORTEST_SINGLE, 0, buffer, &sign, &length, &point);
  78. CHECK_EQ("0", buffer.start());
  79. CHECK_EQ(1, point);
  80. DoubleToAscii(0.0, FIXED, 2, buffer, &sign, &length, &point);
  81. CHECK_EQ(1, length);
  82. CHECK_EQ("0", buffer.start());
  83. CHECK_EQ(1, point);
  84. DoubleToAscii(0.0, PRECISION, 3, buffer, &sign, &length, &point);
  85. CHECK_EQ(1, length);
  86. CHECK_EQ("0", buffer.start());
  87. CHECK_EQ(1, point);
  88. DoubleToAscii(1.0, SHORTEST, 0, buffer, &sign, &length, &point);
  89. CHECK_EQ("1", buffer.start());
  90. CHECK_EQ(1, point);
  91. DoubleToAscii(1.0f, SHORTEST_SINGLE, 0, buffer, &sign, &length, &point);
  92. CHECK_EQ("1", buffer.start());
  93. CHECK_EQ(1, point);
  94. DoubleToAscii(1.0, FIXED, 3, buffer, &sign, &length, &point);
  95. CHECK_GE(3, length - point);
  96. TrimRepresentation(buffer);
  97. CHECK_EQ("1", buffer.start());
  98. CHECK_EQ(1, point);
  99. DoubleToAscii(1.0, PRECISION, 3, buffer, &sign, &length, &point);
  100. CHECK_GE(3, length);
  101. TrimRepresentation(buffer);
  102. CHECK_EQ("1", buffer.start());
  103. CHECK_EQ(1, point);
  104. DoubleToAscii(1.5, SHORTEST, 0, buffer, &sign, &length, &point);
  105. CHECK_EQ("15", buffer.start());
  106. CHECK_EQ(1, point);
  107. DoubleToAscii(1.5f, SHORTEST_SINGLE, 0, buffer, &sign, &length, &point);
  108. CHECK_EQ("15", buffer.start());
  109. CHECK_EQ(1, point);
  110. DoubleToAscii(1.5, FIXED, 10, buffer, &sign, &length, &point);
  111. CHECK_GE(10, length - point);
  112. TrimRepresentation(buffer);
  113. CHECK_EQ("15", buffer.start());
  114. CHECK_EQ(1, point);
  115. DoubleToAscii(1.5, PRECISION, 10, buffer, &sign, &length, &point);
  116. CHECK_GE(10, length);
  117. TrimRepresentation(buffer);
  118. CHECK_EQ("15", buffer.start());
  119. CHECK_EQ(1, point);
  120. double min_double = 5e-324;
  121. DoubleToAscii(min_double, SHORTEST, 0, buffer, &sign, &length, &point);
  122. CHECK_EQ("5", buffer.start());
  123. CHECK_EQ(-323, point);
  124. float min_float = 1e-45f;
  125. DoubleToAscii(min_float, SHORTEST_SINGLE, 0, buffer, &sign, &length, &point);
  126. CHECK_EQ("1", buffer.start());
  127. CHECK_EQ(-44, point);
  128. DoubleToAscii(min_double, FIXED, 5, buffer, &sign, &length, &point);
  129. CHECK_GE(5, length - point);
  130. TrimRepresentation(buffer);
  131. CHECK_EQ("", buffer.start());
  132. CHECK_GE(-5, point);
  133. DoubleToAscii(min_double, PRECISION, 5, buffer, &sign, &length, &point);
  134. CHECK_GE(5, length);
  135. TrimRepresentation(buffer);
  136. CHECK_EQ("49407", buffer.start());
  137. CHECK_EQ(-323, point);
  138. double max_double = 1.7976931348623157e308;
  139. DoubleToAscii(max_double, SHORTEST, 0, buffer, &sign, &length, &point);
  140. CHECK_EQ("17976931348623157", buffer.start());
  141. CHECK_EQ(309, point);
  142. float max_float = 3.4028234e38f;
  143. DoubleToAscii(max_float, SHORTEST_SINGLE, 0,
  144. buffer, &sign, &length, &point);
  145. CHECK_EQ("34028235", buffer.start());
  146. CHECK_EQ(39, point);
  147. DoubleToAscii(max_double, PRECISION, 7, buffer, &sign, &length, &point);
  148. CHECK_GE(7, length);
  149. TrimRepresentation(buffer);
  150. CHECK_EQ("1797693", buffer.start());
  151. CHECK_EQ(309, point);
  152. DoubleToAscii(4294967272.0, SHORTEST, 0, buffer, &sign, &length, &point);
  153. CHECK_EQ("4294967272", buffer.start());
  154. CHECK_EQ(10, point);
  155. DoubleToAscii(4294967272.0f, SHORTEST_SINGLE, 0, buffer, &sign, &length, &point);
  156. CHECK_EQ("42949673", buffer.start());
  157. CHECK_EQ(10, point);
  158. DoubleToAscii(4294967272.0, FIXED, 5, buffer, &sign, &length, &point);
  159. CHECK_GE(5, length - point);
  160. TrimRepresentation(buffer);
  161. CHECK_EQ("4294967272", buffer.start());
  162. CHECK_EQ(10, point);
  163. DoubleToAscii(4294967272.0, PRECISION, 14,
  164. buffer, &sign, &length, &point);
  165. CHECK_GE(14, length);
  166. TrimRepresentation(buffer);
  167. CHECK_EQ("4294967272", buffer.start());
  168. CHECK_EQ(10, point);
  169. DoubleToAscii(4.1855804968213567e298, SHORTEST, 0,
  170. buffer, &sign, &length, &point);
  171. CHECK_EQ("4185580496821357", buffer.start());
  172. CHECK_EQ(299, point);
  173. DoubleToAscii(4.1855804968213567e298, PRECISION, 20,
  174. buffer, &sign, &length, &point);
  175. CHECK_GE(20, length);
  176. TrimRepresentation(buffer);
  177. CHECK_EQ("41855804968213567225", buffer.start());
  178. CHECK_EQ(299, point);
  179. DoubleToAscii(5.5626846462680035e-309, SHORTEST, 0,
  180. buffer, &sign, &length, &point);
  181. CHECK_EQ("5562684646268003", buffer.start());
  182. CHECK_EQ(-308, point);
  183. DoubleToAscii(5.5626846462680035e-309, PRECISION, 1,
  184. buffer, &sign, &length, &point);
  185. CHECK_GE(1, length);
  186. TrimRepresentation(buffer);
  187. CHECK_EQ("6", buffer.start());
  188. CHECK_EQ(-308, point);
  189. DoubleToAscii(-2147483648.0, SHORTEST, 0,
  190. buffer, &sign, &length, &point);
  191. CHECK_EQ(1, sign);
  192. CHECK_EQ("2147483648", buffer.start());
  193. CHECK_EQ(10, point);
  194. DoubleToAscii(-2147483648.0, SHORTEST_SINGLE, 0,
  195. buffer, &sign, &length, &point);
  196. CHECK_EQ(1, sign);
  197. CHECK_EQ("21474836", buffer.start());
  198. CHECK_EQ(10, point);
  199. DoubleToAscii(-2147483648.0, FIXED, 2, buffer, &sign, &length, &point);
  200. CHECK_GE(2, length - point);
  201. TrimRepresentation(buffer);
  202. CHECK_EQ(1, sign);
  203. CHECK_EQ("2147483648", buffer.start());
  204. CHECK_EQ(10, point);
  205. DoubleToAscii(-2147483648.0, PRECISION, 5,
  206. buffer, &sign, &length, &point);
  207. CHECK_GE(5, length);
  208. TrimRepresentation(buffer);
  209. CHECK_EQ(1, sign);
  210. CHECK_EQ("21475", buffer.start());
  211. CHECK_EQ(10, point);
  212. DoubleToAscii(-3.5844466002796428e+298, SHORTEST, 0,
  213. buffer, &sign, &length, &point);
  214. CHECK_EQ(1, sign);
  215. CHECK_EQ("35844466002796428", buffer.start());
  216. CHECK_EQ(299, point);
  217. DoubleToAscii(-3.5844466002796428e+298, PRECISION, 10,
  218. buffer, &sign, &length, &point);
  219. CHECK_EQ(1, sign);
  220. CHECK_GE(10, length);
  221. TrimRepresentation(buffer);
  222. CHECK_EQ("35844466", buffer.start());
  223. CHECK_EQ(299, point);
  224. uint64_t smallest_normal64 = UINT64_2PART_C(0x00100000, 00000000);
  225. double v = Double(smallest_normal64).value();
  226. DoubleToAscii(v, SHORTEST, 0, buffer, &sign, &length, &point);
  227. CHECK_EQ("22250738585072014", buffer.start());
  228. CHECK_EQ(-307, point);
  229. uint32_t smallest_normal32 = 0x00800000;
  230. float f = Single(smallest_normal32).value();
  231. DoubleToAscii(f, SHORTEST_SINGLE, 0, buffer, &sign, &length, &point);
  232. CHECK_EQ("11754944", buffer.start());
  233. CHECK_EQ(-37, point);
  234. DoubleToAscii(v, PRECISION, 20, buffer, &sign, &length, &point);
  235. CHECK_GE(20, length);
  236. TrimRepresentation(buffer);
  237. CHECK_EQ("22250738585072013831", buffer.start());
  238. CHECK_EQ(-307, point);
  239. uint64_t largest_denormal64 = UINT64_2PART_C(0x000FFFFF, FFFFFFFF);
  240. v = Double(largest_denormal64).value();
  241. DoubleToAscii(v, SHORTEST, 0, buffer, &sign, &length, &point);
  242. CHECK_EQ("2225073858507201", buffer.start());
  243. CHECK_EQ(-307, point);
  244. uint32_t largest_denormal32 = 0x007FFFFF;
  245. f = Single(largest_denormal32).value();
  246. DoubleToAscii(f, SHORTEST_SINGLE, 0, buffer, &sign, &length, &point);
  247. CHECK_EQ("11754942", buffer.start());
  248. CHECK_EQ(-37, point);
  249. DoubleToAscii(v, PRECISION, 20, buffer, &sign, &length, &point);
  250. CHECK_GE(20, length);
  251. TrimRepresentation(buffer);
  252. CHECK_EQ("2225073858507200889", buffer.start());
  253. CHECK_EQ(-307, point);
  254. DoubleToAscii(4128420500802942e-24, SHORTEST, 0,
  255. buffer, &sign, &length, &point);
  256. CHECK_EQ(0, sign);
  257. CHECK_EQ("4128420500802942", buffer.start());
  258. CHECK_EQ(-8, point);
  259. v = -3.9292015898194142585311918e-10;
  260. DoubleToAscii(v, SHORTEST, 0, buffer, &sign, &length, &point);
  261. CHECK_EQ("39292015898194143", buffer.start());
  262. f = -3.9292015898194142585311918e-10f;
  263. DoubleToAscii(f, SHORTEST_SINGLE, 0, buffer, &sign, &length, &point);
  264. CHECK_EQ("39292017", buffer.start());
  265. v = 4194304.0;
  266. DoubleToAscii(v, FIXED, 5, buffer, &sign, &length, &point);
  267. CHECK_GE(5, length - point);
  268. TrimRepresentation(buffer);
  269. CHECK_EQ("4194304", buffer.start());
  270. v = 3.3161339052167390562200598e-237;
  271. DoubleToAscii(v, PRECISION, 19, buffer, &sign, &length, &point);
  272. CHECK_GE(19, length);
  273. TrimRepresentation(buffer);
  274. CHECK_EQ("3316133905216739056", buffer.start());
  275. CHECK_EQ(-236, point);
  276. }
  277. TEST(DtoaSign) {
  278. char buffer_container[kBufferSize];
  279. Vector<char> buffer(buffer_container, kBufferSize);
  280. bool sign;
  281. int length;
  282. int point;
  283. DoubleToAscii(0.0, SHORTEST, 0, buffer, &sign, &length, &point);
  284. CHECK(!sign);
  285. DoubleToAscii(-0.0, SHORTEST, 0, buffer, &sign, &length, &point);
  286. CHECK(sign);
  287. DoubleToAscii(1.0, SHORTEST, 0, buffer, &sign, &length, &point);
  288. CHECK(!sign);
  289. DoubleToAscii(-1.0, SHORTEST, 0, buffer, &sign, &length, &point);
  290. CHECK(sign);
  291. DoubleToAscii(0.0f, SHORTEST_SINGLE, 0, buffer, &sign, &length, &point);
  292. CHECK(!sign);
  293. DoubleToAscii(-0.0f, SHORTEST_SINGLE, 0, buffer, &sign, &length, &point);
  294. CHECK(sign);
  295. DoubleToAscii(1.0f, SHORTEST_SINGLE, 0, buffer, &sign, &length, &point);
  296. CHECK(!sign);
  297. DoubleToAscii(-1.0f, SHORTEST_SINGLE, 0, buffer, &sign, &length, &point);
  298. CHECK(sign);
  299. DoubleToAscii(0.0, PRECISION, 1, buffer, &sign, &length, &point);
  300. CHECK(!sign);
  301. DoubleToAscii(-0.0, PRECISION, 1, buffer, &sign, &length, &point);
  302. CHECK(sign);
  303. DoubleToAscii(1.0, PRECISION, 1, buffer, &sign, &length, &point);
  304. CHECK(!sign);
  305. DoubleToAscii(-1.0, PRECISION, 1, buffer, &sign, &length, &point);
  306. CHECK(sign);
  307. DoubleToAscii(0.0, FIXED, 1, buffer, &sign, &length, &point);
  308. CHECK(!sign);
  309. DoubleToAscii(-0.0, FIXED, 1, buffer, &sign, &length, &point);
  310. CHECK(sign);
  311. DoubleToAscii(1.0, FIXED, 1, buffer, &sign, &length, &point);
  312. CHECK(!sign);
  313. DoubleToAscii(-1.0, FIXED, 1, buffer, &sign, &length, &point);
  314. CHECK(sign);
  315. }
  316. TEST(DtoaCorners) {
  317. char buffer_container[kBufferSize];
  318. Vector<char> buffer(buffer_container, kBufferSize);
  319. bool sign;
  320. int length;
  321. int point;
  322. DoubleToAscii(0.0, PRECISION, 0, buffer, &sign, &length, &point);
  323. CHECK_EQ(0, length);
  324. CHECK_EQ("", buffer.start());
  325. CHECK(!sign);
  326. DoubleToAscii(1.0, PRECISION, 0, buffer, &sign, &length, &point);
  327. CHECK_EQ(0, length);
  328. CHECK_EQ("", buffer.start());
  329. CHECK(!sign);
  330. DoubleToAscii(0.0, FIXED, 0, buffer, &sign, &length, &point);
  331. CHECK_EQ(1, length);
  332. CHECK_EQ("0", buffer.start());
  333. CHECK(!sign);
  334. DoubleToAscii(1.0, FIXED, 0, buffer, &sign, &length, &point);
  335. CHECK_EQ(1, length);
  336. CHECK_EQ("1", buffer.start());
  337. CHECK(!sign);
  338. }
  339. TEST(DtoaGayShortest) {
  340. char buffer_container[kBufferSize];
  341. Vector<char> buffer(buffer_container, kBufferSize);
  342. bool sign;
  343. int length;
  344. int point;
  345. Vector<const PrecomputedShortest> precomputed =
  346. PrecomputedShortestRepresentations();
  347. for (int i = 0; i < precomputed.length(); ++i) {
  348. const PrecomputedShortest current_test = precomputed[i];
  349. double v = current_test.v;
  350. DoubleToAscii(v, SHORTEST, 0, buffer, &sign, &length, &point);
  351. CHECK(!sign); // All precomputed numbers are positive.
  352. CHECK_EQ(current_test.decimal_point, point);
  353. CHECK_EQ(current_test.representation, buffer.start());
  354. }
  355. }
  356. TEST(DtoaGayShortestSingle) {
  357. char buffer_container[kBufferSize];
  358. Vector<char> buffer(buffer_container, kBufferSize);
  359. bool sign;
  360. int length;
  361. int point;
  362. Vector<const PrecomputedShortestSingle> precomputed =
  363. PrecomputedShortestSingleRepresentations();
  364. for (int i = 0; i < precomputed.length(); ++i) {
  365. const PrecomputedShortestSingle current_test = precomputed[i];
  366. float v = current_test.v;
  367. DoubleToAscii(v, SHORTEST_SINGLE, 0, buffer, &sign, &length, &point);
  368. CHECK(!sign); // All precomputed numbers are positive.
  369. CHECK_EQ(current_test.decimal_point, point);
  370. CHECK_EQ(current_test.representation, buffer.start());
  371. }
  372. }
  373. TEST(DtoaGayFixed) {
  374. char buffer_container[kBufferSize];
  375. Vector<char> buffer(buffer_container, kBufferSize);
  376. bool sign;
  377. int length;
  378. int point;
  379. Vector<const PrecomputedFixed> precomputed =
  380. PrecomputedFixedRepresentations();
  381. for (int i = 0; i < precomputed.length(); ++i) {
  382. const PrecomputedFixed current_test = precomputed[i];
  383. double v = current_test.v;
  384. int number_digits = current_test.number_digits;
  385. DoubleToAscii(v, FIXED, number_digits, buffer, &sign, &length, &point);
  386. CHECK(!sign); // All precomputed numbers are positive.
  387. CHECK_EQ(current_test.decimal_point, point);
  388. CHECK_GE(number_digits, length - point);
  389. TrimRepresentation(buffer);
  390. CHECK_EQ(current_test.representation, buffer.start());
  391. }
  392. }
  393. TEST(DtoaGayPrecision) {
  394. char buffer_container[kBufferSize];
  395. Vector<char> buffer(buffer_container, kBufferSize);
  396. bool sign;
  397. int length;
  398. int point;
  399. Vector<const PrecomputedPrecision> precomputed =
  400. PrecomputedPrecisionRepresentations();
  401. for (int i = 0; i < precomputed.length(); ++i) {
  402. const PrecomputedPrecision current_test = precomputed[i];
  403. double v = current_test.v;
  404. int number_digits = current_test.number_digits;
  405. DoubleToAscii(v, PRECISION, number_digits,
  406. buffer, &sign, &length, &point);
  407. CHECK(!sign); // All precomputed numbers are positive.
  408. CHECK_EQ(current_test.decimal_point, point);
  409. CHECK_GE(number_digits, length);
  410. TrimRepresentation(buffer);
  411. CHECK_EQ(current_test.representation, buffer.start());
  412. }
  413. }