test-fast-dtoa.cc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. // Copyright 2006-2008 the V8 project authors. All rights reserved.
  2. #include <stdlib.h>
  3. #include "cctest.h"
  4. #include "diy-fp.h"
  5. #include "fast-dtoa.h"
  6. #include "gay-precision.h"
  7. #include "gay-shortest.h"
  8. #include "gay-shortest-single.h"
  9. #include "ieee.h"
  10. #include "utils.h"
  11. using namespace double_conversion;
  12. static const int kBufferSize = 100;
  13. // Removes trailing '0' digits.
  14. static void TrimRepresentation(Vector<char> representation) {
  15. int len = strlen(representation.start());
  16. int i;
  17. for (i = len - 1; i >= 0; --i) {
  18. if (representation[i] != '0') break;
  19. }
  20. representation[i + 1] = '\0';
  21. }
  22. TEST(FastDtoaShortestVariousDoubles) {
  23. char buffer_container[kBufferSize];
  24. Vector<char> buffer(buffer_container, kBufferSize);
  25. int length;
  26. int point;
  27. bool status;
  28. double min_double = 5e-324;
  29. status = FastDtoa(min_double, FAST_DTOA_SHORTEST, 0,
  30. buffer, &length, &point);
  31. CHECK(status);
  32. CHECK_EQ("5", buffer.start());
  33. CHECK_EQ(-323, point);
  34. double max_double = 1.7976931348623157e308;
  35. status = FastDtoa(max_double, FAST_DTOA_SHORTEST, 0,
  36. buffer, &length, &point);
  37. CHECK(status);
  38. CHECK_EQ("17976931348623157", buffer.start());
  39. CHECK_EQ(309, point);
  40. status = FastDtoa(4294967272.0, FAST_DTOA_SHORTEST, 0,
  41. buffer, &length, &point);
  42. CHECK(status);
  43. CHECK_EQ("4294967272", buffer.start());
  44. CHECK_EQ(10, point);
  45. status = FastDtoa(4.1855804968213567e298, FAST_DTOA_SHORTEST, 0,
  46. buffer, &length, &point);
  47. CHECK(status);
  48. CHECK_EQ("4185580496821357", buffer.start());
  49. CHECK_EQ(299, point);
  50. status = FastDtoa(5.5626846462680035e-309, FAST_DTOA_SHORTEST, 0,
  51. buffer, &length, &point);
  52. CHECK(status);
  53. CHECK_EQ("5562684646268003", buffer.start());
  54. CHECK_EQ(-308, point);
  55. status = FastDtoa(2147483648.0, FAST_DTOA_SHORTEST, 0,
  56. buffer, &length, &point);
  57. CHECK(status);
  58. CHECK_EQ("2147483648", buffer.start());
  59. CHECK_EQ(10, point);
  60. status = FastDtoa(3.5844466002796428e+298, FAST_DTOA_SHORTEST, 0,
  61. buffer, &length, &point);
  62. if (status) { // Not all FastDtoa variants manage to compute this number.
  63. CHECK_EQ("35844466002796428", buffer.start());
  64. CHECK_EQ(299, point);
  65. }
  66. uint64_t smallest_normal64 = UINT64_2PART_C(0x00100000, 00000000);
  67. double v = Double(smallest_normal64).value();
  68. status = FastDtoa(v, FAST_DTOA_SHORTEST, 0, buffer, &length, &point);
  69. if (status) {
  70. CHECK_EQ("22250738585072014", buffer.start());
  71. CHECK_EQ(-307, point);
  72. }
  73. uint64_t largest_denormal64 = UINT64_2PART_C(0x000FFFFF, FFFFFFFF);
  74. v = Double(largest_denormal64).value();
  75. status = FastDtoa(v, FAST_DTOA_SHORTEST, 0, buffer, &length, &point);
  76. if (status) {
  77. CHECK_EQ("2225073858507201", buffer.start());
  78. CHECK_EQ(-307, point);
  79. }
  80. }
  81. TEST(FastDtoaShortestVariousFloats) {
  82. char buffer_container[kBufferSize];
  83. Vector<char> buffer(buffer_container, kBufferSize);
  84. int length;
  85. int point;
  86. bool status;
  87. float min_float = 1e-45f;
  88. status = FastDtoa(min_float, FAST_DTOA_SHORTEST_SINGLE, 0,
  89. buffer, &length, &point);
  90. CHECK(status);
  91. CHECK_EQ("1", buffer.start());
  92. CHECK_EQ(-44, point);
  93. float max_float = 3.4028234e38f;
  94. status = FastDtoa(max_float, FAST_DTOA_SHORTEST_SINGLE, 0,
  95. buffer, &length, &point);
  96. CHECK(status);
  97. CHECK_EQ("34028235", buffer.start());
  98. CHECK_EQ(39, point);
  99. status = FastDtoa(4294967272.0f, FAST_DTOA_SHORTEST_SINGLE, 0,
  100. buffer, &length, &point);
  101. CHECK(status);
  102. CHECK_EQ("42949673", buffer.start());
  103. CHECK_EQ(10, point);
  104. status = FastDtoa(3.32306998946228968226e+35f, FAST_DTOA_SHORTEST_SINGLE, 0,
  105. buffer, &length, &point);
  106. CHECK(status);
  107. CHECK_EQ("332307", buffer.start());
  108. CHECK_EQ(36, point);
  109. status = FastDtoa(1.2341e-41f, FAST_DTOA_SHORTEST_SINGLE, 0,
  110. buffer, &length, &point);
  111. CHECK(status);
  112. CHECK_EQ("12341", buffer.start());
  113. CHECK_EQ(-40, point);
  114. status = FastDtoa(3.3554432e7, FAST_DTOA_SHORTEST_SINGLE, 0,
  115. buffer, &length, &point);
  116. CHECK(status);
  117. CHECK_EQ("33554432", buffer.start());
  118. CHECK_EQ(8, point);
  119. status = FastDtoa(3.26494756798464e14f, FAST_DTOA_SHORTEST_SINGLE, 0,
  120. buffer, &length, &point);
  121. CHECK(status);
  122. CHECK_EQ("32649476", buffer.start());
  123. CHECK_EQ(15, point);
  124. status = FastDtoa(3.91132223637771935344e37f, FAST_DTOA_SHORTEST_SINGLE, 0,
  125. buffer, &length, &point);
  126. if (status) { // Not all FastDtoa variants manage to compute this number.
  127. CHECK_EQ("39113222", buffer.start());
  128. CHECK_EQ(38, point);
  129. }
  130. uint32_t smallest_normal32 = 0x00800000;
  131. float v = Single(smallest_normal32).value();
  132. status = FastDtoa(v, FAST_DTOA_SHORTEST_SINGLE, 0, buffer, &length, &point);
  133. if (status) {
  134. CHECK_EQ("11754944", buffer.start());
  135. CHECK_EQ(-37, point);
  136. }
  137. uint32_t largest_denormal32 = 0x007FFFFF;
  138. v = Single(largest_denormal32).value();
  139. status = FastDtoa(v, FAST_DTOA_SHORTEST_SINGLE, 0, buffer, &length, &point);
  140. CHECK(status);
  141. CHECK_EQ("11754942", buffer.start());
  142. CHECK_EQ(-37, point);
  143. }
  144. TEST(FastDtoaPrecisionVariousDoubles) {
  145. char buffer_container[kBufferSize];
  146. Vector<char> buffer(buffer_container, kBufferSize);
  147. int length;
  148. int point;
  149. bool status;
  150. status = FastDtoa(1.0, FAST_DTOA_PRECISION, 3, buffer, &length, &point);
  151. CHECK(status);
  152. CHECK(3 >= length);
  153. TrimRepresentation(buffer);
  154. CHECK_EQ("1", buffer.start());
  155. CHECK_EQ(1, point);
  156. status = FastDtoa(1.5, FAST_DTOA_PRECISION, 10, buffer, &length, &point);
  157. if (status) {
  158. CHECK(10 >= length);
  159. TrimRepresentation(buffer);
  160. CHECK_EQ("15", buffer.start());
  161. CHECK_EQ(1, point);
  162. }
  163. double min_double = 5e-324;
  164. status = FastDtoa(min_double, FAST_DTOA_PRECISION, 5,
  165. buffer, &length, &point);
  166. CHECK(status);
  167. CHECK_EQ("49407", buffer.start());
  168. CHECK_EQ(-323, point);
  169. double max_double = 1.7976931348623157e308;
  170. status = FastDtoa(max_double, FAST_DTOA_PRECISION, 7,
  171. buffer, &length, &point);
  172. CHECK(status);
  173. CHECK_EQ("1797693", buffer.start());
  174. CHECK_EQ(309, point);
  175. status = FastDtoa(4294967272.0, FAST_DTOA_PRECISION, 14,
  176. buffer, &length, &point);
  177. if (status) {
  178. CHECK(14 >= length);
  179. TrimRepresentation(buffer);
  180. CHECK_EQ("4294967272", buffer.start());
  181. CHECK_EQ(10, point);
  182. }
  183. status = FastDtoa(4.1855804968213567e298, FAST_DTOA_PRECISION, 17,
  184. buffer, &length, &point);
  185. CHECK(status);
  186. CHECK_EQ("41855804968213567", buffer.start());
  187. CHECK_EQ(299, point);
  188. status = FastDtoa(5.5626846462680035e-309, FAST_DTOA_PRECISION, 1,
  189. buffer, &length, &point);
  190. CHECK(status);
  191. CHECK_EQ("6", buffer.start());
  192. CHECK_EQ(-308, point);
  193. status = FastDtoa(2147483648.0, FAST_DTOA_PRECISION, 5,
  194. buffer, &length, &point);
  195. CHECK(status);
  196. CHECK_EQ("21475", buffer.start());
  197. CHECK_EQ(10, point);
  198. status = FastDtoa(3.5844466002796428e+298, FAST_DTOA_PRECISION, 10,
  199. buffer, &length, &point);
  200. CHECK(status);
  201. CHECK(10 >= length);
  202. TrimRepresentation(buffer);
  203. CHECK_EQ("35844466", buffer.start());
  204. CHECK_EQ(299, point);
  205. uint64_t smallest_normal64 = UINT64_2PART_C(0x00100000, 00000000);
  206. double v = Double(smallest_normal64).value();
  207. status = FastDtoa(v, FAST_DTOA_PRECISION, 17, buffer, &length, &point);
  208. CHECK(status);
  209. CHECK_EQ("22250738585072014", buffer.start());
  210. CHECK_EQ(-307, point);
  211. uint64_t largest_denormal64 = UINT64_2PART_C(0x000FFFFF, FFFFFFFF);
  212. v = Double(largest_denormal64).value();
  213. status = FastDtoa(v, FAST_DTOA_PRECISION, 17, buffer, &length, &point);
  214. CHECK(status);
  215. CHECK(20 >= length);
  216. TrimRepresentation(buffer);
  217. CHECK_EQ("22250738585072009", buffer.start());
  218. CHECK_EQ(-307, point);
  219. v = 3.3161339052167390562200598e-237;
  220. status = FastDtoa(v, FAST_DTOA_PRECISION, 18, buffer, &length, &point);
  221. CHECK(status);
  222. CHECK_EQ("331613390521673906", buffer.start());
  223. CHECK_EQ(-236, point);
  224. v = 7.9885183916008099497815232e+191;
  225. status = FastDtoa(v, FAST_DTOA_PRECISION, 4, buffer, &length, &point);
  226. CHECK(status);
  227. CHECK_EQ("7989", buffer.start());
  228. CHECK_EQ(192, point);
  229. }
  230. TEST(FastDtoaGayShortest) {
  231. char buffer_container[kBufferSize];
  232. Vector<char> buffer(buffer_container, kBufferSize);
  233. bool status;
  234. int length;
  235. int point;
  236. int succeeded = 0;
  237. int total = 0;
  238. bool needed_max_length = false;
  239. Vector<const PrecomputedShortest> precomputed =
  240. PrecomputedShortestRepresentations();
  241. for (int i = 0; i < precomputed.length(); ++i) {
  242. const PrecomputedShortest current_test = precomputed[i];
  243. total++;
  244. double v = current_test.v;
  245. status = FastDtoa(v, FAST_DTOA_SHORTEST, 0, buffer, &length, &point);
  246. CHECK(kFastDtoaMaximalLength >= length);
  247. if (!status) continue;
  248. if (length == kFastDtoaMaximalLength) needed_max_length = true;
  249. succeeded++;
  250. CHECK_EQ(current_test.decimal_point, point);
  251. CHECK_EQ(current_test.representation, buffer.start());
  252. }
  253. CHECK(succeeded*1.0/total > 0.99);
  254. CHECK(needed_max_length);
  255. }
  256. TEST(FastDtoaGayShortestSingle) {
  257. char buffer_container[kBufferSize];
  258. Vector<char> buffer(buffer_container, kBufferSize);
  259. bool status;
  260. int length;
  261. int point;
  262. int succeeded = 0;
  263. int total = 0;
  264. bool needed_max_length = false;
  265. Vector<const PrecomputedShortestSingle> precomputed =
  266. PrecomputedShortestSingleRepresentations();
  267. for (int i = 0; i < precomputed.length(); ++i) {
  268. const PrecomputedShortestSingle current_test = precomputed[i];
  269. total++;
  270. float v = current_test.v;
  271. status = FastDtoa(v, FAST_DTOA_SHORTEST_SINGLE, 0, buffer, &length, &point);
  272. CHECK(kFastDtoaMaximalSingleLength >= length);
  273. if (!status) continue;
  274. if (length == kFastDtoaMaximalSingleLength) needed_max_length = true;
  275. succeeded++;
  276. CHECK_EQ(current_test.decimal_point, point);
  277. CHECK_EQ(current_test.representation, buffer.start());
  278. }
  279. CHECK(succeeded*1.0/total > 0.98);
  280. CHECK(needed_max_length);
  281. }
  282. TEST(FastDtoaGayPrecision) {
  283. char buffer_container[kBufferSize];
  284. Vector<char> buffer(buffer_container, kBufferSize);
  285. bool status;
  286. int length;
  287. int point;
  288. int succeeded = 0;
  289. int total = 0;
  290. // Count separately for entries with less than 15 requested digits.
  291. int succeeded_15 = 0;
  292. int total_15 = 0;
  293. Vector<const PrecomputedPrecision> precomputed =
  294. PrecomputedPrecisionRepresentations();
  295. for (int i = 0; i < precomputed.length(); ++i) {
  296. const PrecomputedPrecision current_test = precomputed[i];
  297. double v = current_test.v;
  298. int number_digits = current_test.number_digits;
  299. total++;
  300. if (number_digits <= 15) total_15++;
  301. status = FastDtoa(v, FAST_DTOA_PRECISION, number_digits,
  302. buffer, &length, &point);
  303. CHECK(number_digits >= length);
  304. if (!status) continue;
  305. succeeded++;
  306. if (number_digits <= 15) succeeded_15++;
  307. TrimRepresentation(buffer);
  308. CHECK_EQ(current_test.decimal_point, point);
  309. CHECK_EQ(current_test.representation, buffer.start());
  310. }
  311. // The precomputed numbers contain many entries with many requested
  312. // digits. These have a high failure rate and we therefore expect a lower
  313. // success rate than for the shortest representation.
  314. CHECK(succeeded*1.0/total > 0.85);
  315. // However with less than 15 digits almost the algorithm should almost always
  316. // succeed.
  317. CHECK(succeeded_15*1.0/total_15 > 0.9999);
  318. }