quickfix_ruby 1.14.3.1 → 1.15.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (105) hide show
  1. checksums.yaml +4 -4
  2. data/ext/quickfix/Acceptor.h +2 -0
  3. data/ext/quickfix/AtomicCount.h +82 -12
  4. data/ext/quickfix/DOMDocument.h +9 -7
  5. data/ext/quickfix/DataDictionary.cpp +77 -14
  6. data/ext/quickfix/DataDictionary.h +90 -16
  7. data/ext/quickfix/Dictionary.cpp +1 -2
  8. data/ext/quickfix/Exceptions.h +3 -5
  9. data/ext/quickfix/Field.h +83 -32
  10. data/ext/quickfix/FieldConvertors.cpp +93 -0
  11. data/ext/quickfix/FieldConvertors.h +129 -275
  12. data/ext/quickfix/FieldMap.cpp +53 -13
  13. data/ext/quickfix/FieldMap.h +200 -62
  14. data/ext/quickfix/FieldTypes.cpp +10 -10
  15. data/ext/quickfix/FieldTypes.h +293 -44
  16. data/ext/quickfix/FileLog.cpp +6 -10
  17. data/ext/quickfix/FileLog.h +4 -10
  18. data/ext/quickfix/FileStore.cpp +19 -6
  19. data/ext/quickfix/FileStore.h +4 -0
  20. data/ext/quickfix/FixFieldNumbers.h +1462 -1461
  21. data/ext/quickfix/FixFields.h +1462 -1461
  22. data/ext/quickfix/FixValues.h +3230 -3227
  23. data/ext/quickfix/HttpConnection.cpp +1 -1
  24. data/ext/quickfix/Initiator.cpp +7 -1
  25. data/ext/quickfix/Initiator.h +2 -0
  26. data/ext/quickfix/Log.h +6 -12
  27. data/ext/quickfix/Message.cpp +186 -57
  28. data/ext/quickfix/Message.h +109 -47
  29. data/ext/quickfix/MySQLConnection.h +1 -1
  30. data/ext/quickfix/PostgreSQLConnection.h +1 -1
  31. data/ext/quickfix/QuickfixRuby.cpp +79141 -77959
  32. data/ext/quickfix/QuickfixRuby.h +1 -1
  33. data/ext/quickfix/SSLSocketAcceptor.cpp +410 -0
  34. data/ext/quickfix/SSLSocketAcceptor.h +185 -0
  35. data/ext/quickfix/SSLSocketConnection.cpp +427 -0
  36. data/ext/quickfix/SSLSocketConnection.h +206 -0
  37. data/ext/quickfix/SSLSocketInitiator.cpp +485 -0
  38. data/ext/quickfix/SSLSocketInitiator.h +196 -0
  39. data/ext/quickfix/Session.cpp +113 -20
  40. data/ext/quickfix/Session.h +18 -4
  41. data/ext/quickfix/SessionFactory.cpp +10 -3
  42. data/ext/quickfix/SessionSettings.cpp +5 -3
  43. data/ext/quickfix/SessionSettings.h +97 -5
  44. data/ext/quickfix/Settings.cpp +72 -2
  45. data/ext/quickfix/Settings.h +3 -0
  46. data/ext/quickfix/SharedArray.h +140 -6
  47. data/ext/quickfix/SocketConnection.cpp +2 -2
  48. data/ext/quickfix/SocketConnector.cpp +5 -2
  49. data/ext/quickfix/SocketConnector.h +3 -2
  50. data/ext/quickfix/SocketInitiator.cpp +28 -4
  51. data/ext/quickfix/SocketInitiator.h +1 -1
  52. data/ext/quickfix/SocketMonitor.cpp +5 -5
  53. data/ext/quickfix/ThreadedSSLSocketAcceptor.cpp +455 -0
  54. data/ext/quickfix/ThreadedSSLSocketAcceptor.h +217 -0
  55. data/ext/quickfix/ThreadedSSLSocketConnection.cpp +404 -0
  56. data/ext/quickfix/ThreadedSSLSocketConnection.h +189 -0
  57. data/ext/quickfix/ThreadedSSLSocketInitiator.cpp +469 -0
  58. data/ext/quickfix/ThreadedSSLSocketInitiator.h +201 -0
  59. data/ext/quickfix/ThreadedSocketAcceptor.cpp +5 -1
  60. data/ext/quickfix/ThreadedSocketConnection.cpp +8 -2
  61. data/ext/quickfix/ThreadedSocketConnection.h +4 -1
  62. data/ext/quickfix/ThreadedSocketInitiator.cpp +24 -4
  63. data/ext/quickfix/ThreadedSocketInitiator.h +1 -1
  64. data/ext/quickfix/Utility.cpp +23 -1
  65. data/ext/quickfix/Utility.h +28 -2
  66. data/ext/quickfix/UtilitySSL.cpp +1733 -0
  67. data/ext/quickfix/UtilitySSL.h +277 -0
  68. data/ext/quickfix/config-all.h +10 -0
  69. data/ext/quickfix/dirent_windows.h +838 -0
  70. data/ext/quickfix/double-conversion/bignum-dtoa.cc +641 -0
  71. data/ext/quickfix/double-conversion/bignum-dtoa.h +84 -0
  72. data/ext/quickfix/double-conversion/bignum.cc +766 -0
  73. data/ext/quickfix/double-conversion/bignum.h +144 -0
  74. data/ext/quickfix/double-conversion/cached-powers.cc +176 -0
  75. data/ext/quickfix/double-conversion/cached-powers.h +64 -0
  76. data/ext/quickfix/double-conversion/diy-fp.cc +57 -0
  77. data/ext/quickfix/double-conversion/diy-fp.h +118 -0
  78. data/ext/quickfix/double-conversion/double-conversion.cc +994 -0
  79. data/ext/quickfix/double-conversion/double-conversion.h +543 -0
  80. data/ext/quickfix/double-conversion/fast-dtoa.cc +665 -0
  81. data/ext/quickfix/double-conversion/fast-dtoa.h +88 -0
  82. data/ext/quickfix/double-conversion/fixed-dtoa.cc +404 -0
  83. data/ext/quickfix/double-conversion/fixed-dtoa.h +56 -0
  84. data/ext/quickfix/double-conversion/ieee.h +402 -0
  85. data/ext/quickfix/double-conversion/strtod.cc +557 -0
  86. data/ext/quickfix/double-conversion/strtod.h +45 -0
  87. data/ext/quickfix/double-conversion/utils.h +372 -0
  88. data/ext/quickfix/stdint_msvc.h +254 -0
  89. data/lib/quickfix44.rb +3329 -10
  90. data/lib/quickfix50.rb +6649 -81
  91. data/lib/quickfix50sp1.rb +8054 -142
  92. data/lib/quickfix50sp2.rb +10900 -234
  93. data/lib/quickfix_fields.rb +7662 -7649
  94. data/spec/FIX40.xml +28 -28
  95. data/spec/FIX41.xml +29 -29
  96. data/spec/FIX42.xml +47 -47
  97. data/spec/FIX43.xml +148 -148
  98. data/spec/FIX44.xml +1078 -1081
  99. data/spec/FIX50.xml +1292 -1289
  100. data/spec/FIX50SP1.xml +1811 -1802
  101. data/spec/FIX50SP2.xml +1948 -1939
  102. data/spec/FIXT11.xml +5 -8
  103. data/test/test_FieldBaseTestCase.rb +1 -1
  104. data/test/test_MessageTestCase.rb +2 -2
  105. metadata +42 -6
@@ -0,0 +1,641 @@
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
+
28
+ #include <math.h>
29
+
30
+ #include "bignum-dtoa.h"
31
+
32
+ #include "bignum.h"
33
+ #include "ieee.h"
34
+
35
+ namespace double_conversion {
36
+
37
+ static int NormalizedExponent(uint64_t significand, int exponent) {
38
+ ASSERT(significand != 0);
39
+ while ((significand & Double::kHiddenBit) == 0) {
40
+ significand = significand << 1;
41
+ exponent = exponent - 1;
42
+ }
43
+ return exponent;
44
+ }
45
+
46
+
47
+ // Forward declarations:
48
+ // Returns an estimation of k such that 10^(k-1) <= v < 10^k.
49
+ static int EstimatePower(int exponent);
50
+ // Computes v / 10^estimated_power exactly, as a ratio of two bignums, numerator
51
+ // and denominator.
52
+ static void InitialScaledStartValues(uint64_t significand,
53
+ int exponent,
54
+ bool lower_boundary_is_closer,
55
+ int estimated_power,
56
+ bool need_boundary_deltas,
57
+ Bignum* numerator,
58
+ Bignum* denominator,
59
+ Bignum* delta_minus,
60
+ Bignum* delta_plus);
61
+ // Multiplies numerator/denominator so that its values lies in the range 1-10.
62
+ // Returns decimal_point s.t.
63
+ // v = numerator'/denominator' * 10^(decimal_point-1)
64
+ // where numerator' and denominator' are the values of numerator and
65
+ // denominator after the call to this function.
66
+ static void FixupMultiply10(int estimated_power, bool is_even,
67
+ int* decimal_point,
68
+ Bignum* numerator, Bignum* denominator,
69
+ Bignum* delta_minus, Bignum* delta_plus);
70
+ // Generates digits from the left to the right and stops when the generated
71
+ // digits yield the shortest decimal representation of v.
72
+ static void GenerateShortestDigits(Bignum* numerator, Bignum* denominator,
73
+ Bignum* delta_minus, Bignum* delta_plus,
74
+ bool is_even,
75
+ Vector<char> buffer, int* length);
76
+ // Generates 'requested_digits' after the decimal point.
77
+ static void BignumToFixed(int requested_digits, int* decimal_point,
78
+ Bignum* numerator, Bignum* denominator,
79
+ Vector<char>(buffer), int* length);
80
+ // Generates 'count' digits of numerator/denominator.
81
+ // Once 'count' digits have been produced rounds the result depending on the
82
+ // remainder (remainders of exactly .5 round upwards). Might update the
83
+ // decimal_point when rounding up (for example for 0.9999).
84
+ static void GenerateCountedDigits(int count, int* decimal_point,
85
+ Bignum* numerator, Bignum* denominator,
86
+ Vector<char>(buffer), int* length);
87
+
88
+
89
+ void BignumDtoa(double v, BignumDtoaMode mode, int requested_digits,
90
+ Vector<char> buffer, int* length, int* decimal_point) {
91
+ ASSERT(v > 0);
92
+ ASSERT(!Double(v).IsSpecial());
93
+ uint64_t significand;
94
+ int exponent;
95
+ bool lower_boundary_is_closer;
96
+ if (mode == BIGNUM_DTOA_SHORTEST_SINGLE) {
97
+ float f = static_cast<float>(v);
98
+ ASSERT(f == v);
99
+ significand = Single(f).Significand();
100
+ exponent = Single(f).Exponent();
101
+ lower_boundary_is_closer = Single(f).LowerBoundaryIsCloser();
102
+ } else {
103
+ significand = Double(v).Significand();
104
+ exponent = Double(v).Exponent();
105
+ lower_boundary_is_closer = Double(v).LowerBoundaryIsCloser();
106
+ }
107
+ bool need_boundary_deltas =
108
+ (mode == BIGNUM_DTOA_SHORTEST || mode == BIGNUM_DTOA_SHORTEST_SINGLE);
109
+
110
+ bool is_even = (significand & 1) == 0;
111
+ int normalized_exponent = NormalizedExponent(significand, exponent);
112
+ // estimated_power might be too low by 1.
113
+ int estimated_power = EstimatePower(normalized_exponent);
114
+
115
+ // Shortcut for Fixed.
116
+ // The requested digits correspond to the digits after the point. If the
117
+ // number is much too small, then there is no need in trying to get any
118
+ // digits.
119
+ if (mode == BIGNUM_DTOA_FIXED && -estimated_power - 1 > requested_digits) {
120
+ buffer[0] = '\0';
121
+ *length = 0;
122
+ // Set decimal-point to -requested_digits. This is what Gay does.
123
+ // Note that it should not have any effect anyways since the string is
124
+ // empty.
125
+ *decimal_point = -requested_digits;
126
+ return;
127
+ }
128
+
129
+ Bignum numerator;
130
+ Bignum denominator;
131
+ Bignum delta_minus;
132
+ Bignum delta_plus;
133
+ // Make sure the bignum can grow large enough. The smallest double equals
134
+ // 4e-324. In this case the denominator needs fewer than 324*4 binary digits.
135
+ // The maximum double is 1.7976931348623157e308 which needs fewer than
136
+ // 308*4 binary digits.
137
+ ASSERT(Bignum::kMaxSignificantBits >= 324*4);
138
+ InitialScaledStartValues(significand, exponent, lower_boundary_is_closer,
139
+ estimated_power, need_boundary_deltas,
140
+ &numerator, &denominator,
141
+ &delta_minus, &delta_plus);
142
+ // We now have v = (numerator / denominator) * 10^estimated_power.
143
+ FixupMultiply10(estimated_power, is_even, decimal_point,
144
+ &numerator, &denominator,
145
+ &delta_minus, &delta_plus);
146
+ // We now have v = (numerator / denominator) * 10^(decimal_point-1), and
147
+ // 1 <= (numerator + delta_plus) / denominator < 10
148
+ switch (mode) {
149
+ case BIGNUM_DTOA_SHORTEST:
150
+ case BIGNUM_DTOA_SHORTEST_SINGLE:
151
+ GenerateShortestDigits(&numerator, &denominator,
152
+ &delta_minus, &delta_plus,
153
+ is_even, buffer, length);
154
+ break;
155
+ case BIGNUM_DTOA_FIXED:
156
+ BignumToFixed(requested_digits, decimal_point,
157
+ &numerator, &denominator,
158
+ buffer, length);
159
+ break;
160
+ case BIGNUM_DTOA_PRECISION:
161
+ GenerateCountedDigits(requested_digits, decimal_point,
162
+ &numerator, &denominator,
163
+ buffer, length);
164
+ break;
165
+ default:
166
+ UNREACHABLE();
167
+ }
168
+ buffer[*length] = '\0';
169
+ }
170
+
171
+
172
+ // The procedure starts generating digits from the left to the right and stops
173
+ // when the generated digits yield the shortest decimal representation of v. A
174
+ // decimal representation of v is a number lying closer to v than to any other
175
+ // double, so it converts to v when read.
176
+ //
177
+ // This is true if d, the decimal representation, is between m- and m+, the
178
+ // upper and lower boundaries. d must be strictly between them if !is_even.
179
+ // m- := (numerator - delta_minus) / denominator
180
+ // m+ := (numerator + delta_plus) / denominator
181
+ //
182
+ // Precondition: 0 <= (numerator+delta_plus) / denominator < 10.
183
+ // If 1 <= (numerator+delta_plus) / denominator < 10 then no leading 0 digit
184
+ // will be produced. This should be the standard precondition.
185
+ static void GenerateShortestDigits(Bignum* numerator, Bignum* denominator,
186
+ Bignum* delta_minus, Bignum* delta_plus,
187
+ bool is_even,
188
+ Vector<char> buffer, int* length) {
189
+ // Small optimization: if delta_minus and delta_plus are the same just reuse
190
+ // one of the two bignums.
191
+ if (Bignum::Equal(*delta_minus, *delta_plus)) {
192
+ delta_plus = delta_minus;
193
+ }
194
+ *length = 0;
195
+ for (;;) {
196
+ uint16_t digit;
197
+ digit = numerator->DivideModuloIntBignum(*denominator);
198
+ ASSERT(digit <= 9); // digit is a uint16_t and therefore always positive.
199
+ // digit = numerator / denominator (integer division).
200
+ // numerator = numerator % denominator.
201
+ buffer[(*length)++] = static_cast<char>(digit + '0');
202
+
203
+ // Can we stop already?
204
+ // If the remainder of the division is less than the distance to the lower
205
+ // boundary we can stop. In this case we simply round down (discarding the
206
+ // remainder).
207
+ // Similarly we test if we can round up (using the upper boundary).
208
+ bool in_delta_room_minus;
209
+ bool in_delta_room_plus;
210
+ if (is_even) {
211
+ in_delta_room_minus = Bignum::LessEqual(*numerator, *delta_minus);
212
+ } else {
213
+ in_delta_room_minus = Bignum::Less(*numerator, *delta_minus);
214
+ }
215
+ if (is_even) {
216
+ in_delta_room_plus =
217
+ Bignum::PlusCompare(*numerator, *delta_plus, *denominator) >= 0;
218
+ } else {
219
+ in_delta_room_plus =
220
+ Bignum::PlusCompare(*numerator, *delta_plus, *denominator) > 0;
221
+ }
222
+ if (!in_delta_room_minus && !in_delta_room_plus) {
223
+ // Prepare for next iteration.
224
+ numerator->Times10();
225
+ delta_minus->Times10();
226
+ // We optimized delta_plus to be equal to delta_minus (if they share the
227
+ // same value). So don't multiply delta_plus if they point to the same
228
+ // object.
229
+ if (delta_minus != delta_plus) {
230
+ delta_plus->Times10();
231
+ }
232
+ } else if (in_delta_room_minus && in_delta_room_plus) {
233
+ // Let's see if 2*numerator < denominator.
234
+ // If yes, then the next digit would be < 5 and we can round down.
235
+ int compare = Bignum::PlusCompare(*numerator, *numerator, *denominator);
236
+ if (compare < 0) {
237
+ // Remaining digits are less than .5. -> Round down (== do nothing).
238
+ } else if (compare > 0) {
239
+ // Remaining digits are more than .5 of denominator. -> Round up.
240
+ // Note that the last digit could not be a '9' as otherwise the whole
241
+ // loop would have stopped earlier.
242
+ // We still have an assert here in case the preconditions were not
243
+ // satisfied.
244
+ ASSERT(buffer[(*length) - 1] != '9');
245
+ buffer[(*length) - 1]++;
246
+ } else {
247
+ // Halfway case.
248
+ // TODO(floitsch): need a way to solve half-way cases.
249
+ // For now let's round towards even (since this is what Gay seems to
250
+ // do).
251
+
252
+ if ((buffer[(*length) - 1] - '0') % 2 == 0) {
253
+ // Round down => Do nothing.
254
+ } else {
255
+ ASSERT(buffer[(*length) - 1] != '9');
256
+ buffer[(*length) - 1]++;
257
+ }
258
+ }
259
+ return;
260
+ } else if (in_delta_room_minus) {
261
+ // Round down (== do nothing).
262
+ return;
263
+ } else { // in_delta_room_plus
264
+ // Round up.
265
+ // Note again that the last digit could not be '9' since this would have
266
+ // stopped the loop earlier.
267
+ // We still have an ASSERT here, in case the preconditions were not
268
+ // satisfied.
269
+ ASSERT(buffer[(*length) -1] != '9');
270
+ buffer[(*length) - 1]++;
271
+ return;
272
+ }
273
+ }
274
+ }
275
+
276
+
277
+ // Let v = numerator / denominator < 10.
278
+ // Then we generate 'count' digits of d = x.xxxxx... (without the decimal point)
279
+ // from left to right. Once 'count' digits have been produced we decide wether
280
+ // to round up or down. Remainders of exactly .5 round upwards. Numbers such
281
+ // as 9.999999 propagate a carry all the way, and change the
282
+ // exponent (decimal_point), when rounding upwards.
283
+ static void GenerateCountedDigits(int count, int* decimal_point,
284
+ Bignum* numerator, Bignum* denominator,
285
+ Vector<char> buffer, int* length) {
286
+ ASSERT(count >= 0);
287
+ for (int i = 0; i < count - 1; ++i) {
288
+ uint16_t digit;
289
+ digit = numerator->DivideModuloIntBignum(*denominator);
290
+ ASSERT(digit <= 9); // digit is a uint16_t and therefore always positive.
291
+ // digit = numerator / denominator (integer division).
292
+ // numerator = numerator % denominator.
293
+ buffer[i] = static_cast<char>(digit + '0');
294
+ // Prepare for next iteration.
295
+ numerator->Times10();
296
+ }
297
+ // Generate the last digit.
298
+ uint16_t digit;
299
+ digit = numerator->DivideModuloIntBignum(*denominator);
300
+ if (Bignum::PlusCompare(*numerator, *numerator, *denominator) >= 0) {
301
+ digit++;
302
+ }
303
+ ASSERT(digit <= 10);
304
+ buffer[count - 1] = static_cast<char>(digit + '0');
305
+ // Correct bad digits (in case we had a sequence of '9's). Propagate the
306
+ // carry until we hat a non-'9' or til we reach the first digit.
307
+ for (int i = count - 1; i > 0; --i) {
308
+ if (buffer[i] != '0' + 10) break;
309
+ buffer[i] = '0';
310
+ buffer[i - 1]++;
311
+ }
312
+ if (buffer[0] == '0' + 10) {
313
+ // Propagate a carry past the top place.
314
+ buffer[0] = '1';
315
+ (*decimal_point)++;
316
+ }
317
+ *length = count;
318
+ }
319
+
320
+
321
+ // Generates 'requested_digits' after the decimal point. It might omit
322
+ // trailing '0's. If the input number is too small then no digits at all are
323
+ // generated (ex.: 2 fixed digits for 0.00001).
324
+ //
325
+ // Input verifies: 1 <= (numerator + delta) / denominator < 10.
326
+ static void BignumToFixed(int requested_digits, int* decimal_point,
327
+ Bignum* numerator, Bignum* denominator,
328
+ Vector<char>(buffer), int* length) {
329
+ // Note that we have to look at more than just the requested_digits, since
330
+ // a number could be rounded up. Example: v=0.5 with requested_digits=0.
331
+ // Even though the power of v equals 0 we can't just stop here.
332
+ if (-(*decimal_point) > requested_digits) {
333
+ // The number is definitively too small.
334
+ // Ex: 0.001 with requested_digits == 1.
335
+ // Set decimal-point to -requested_digits. This is what Gay does.
336
+ // Note that it should not have any effect anyways since the string is
337
+ // empty.
338
+ *decimal_point = -requested_digits;
339
+ *length = 0;
340
+ return;
341
+ } else if (-(*decimal_point) == requested_digits) {
342
+ // We only need to verify if the number rounds down or up.
343
+ // Ex: 0.04 and 0.06 with requested_digits == 1.
344
+ ASSERT(*decimal_point == -requested_digits);
345
+ // Initially the fraction lies in range (1, 10]. Multiply the denominator
346
+ // by 10 so that we can compare more easily.
347
+ denominator->Times10();
348
+ if (Bignum::PlusCompare(*numerator, *numerator, *denominator) >= 0) {
349
+ // If the fraction is >= 0.5 then we have to include the rounded
350
+ // digit.
351
+ buffer[0] = '1';
352
+ *length = 1;
353
+ (*decimal_point)++;
354
+ } else {
355
+ // Note that we caught most of similar cases earlier.
356
+ *length = 0;
357
+ }
358
+ return;
359
+ } else {
360
+ // The requested digits correspond to the digits after the point.
361
+ // The variable 'needed_digits' includes the digits before the point.
362
+ int needed_digits = (*decimal_point) + requested_digits;
363
+ GenerateCountedDigits(needed_digits, decimal_point,
364
+ numerator, denominator,
365
+ buffer, length);
366
+ }
367
+ }
368
+
369
+
370
+ // Returns an estimation of k such that 10^(k-1) <= v < 10^k where
371
+ // v = f * 2^exponent and 2^52 <= f < 2^53.
372
+ // v is hence a normalized double with the given exponent. The output is an
373
+ // approximation for the exponent of the decimal approimation .digits * 10^k.
374
+ //
375
+ // The result might undershoot by 1 in which case 10^k <= v < 10^k+1.
376
+ // Note: this property holds for v's upper boundary m+ too.
377
+ // 10^k <= m+ < 10^k+1.
378
+ // (see explanation below).
379
+ //
380
+ // Examples:
381
+ // EstimatePower(0) => 16
382
+ // EstimatePower(-52) => 0
383
+ //
384
+ // Note: e >= 0 => EstimatedPower(e) > 0. No similar claim can be made for e<0.
385
+ static int EstimatePower(int exponent) {
386
+ // This function estimates log10 of v where v = f*2^e (with e == exponent).
387
+ // Note that 10^floor(log10(v)) <= v, but v <= 10^ceil(log10(v)).
388
+ // Note that f is bounded by its container size. Let p = 53 (the double's
389
+ // significand size). Then 2^(p-1) <= f < 2^p.
390
+ //
391
+ // Given that log10(v) == log2(v)/log2(10) and e+(len(f)-1) is quite close
392
+ // to log2(v) the function is simplified to (e+(len(f)-1)/log2(10)).
393
+ // The computed number undershoots by less than 0.631 (when we compute log3
394
+ // and not log10).
395
+ //
396
+ // Optimization: since we only need an approximated result this computation
397
+ // can be performed on 64 bit integers. On x86/x64 architecture the speedup is
398
+ // not really measurable, though.
399
+ //
400
+ // Since we want to avoid overshooting we decrement by 1e10 so that
401
+ // floating-point imprecisions don't affect us.
402
+ //
403
+ // Explanation for v's boundary m+: the computation takes advantage of
404
+ // the fact that 2^(p-1) <= f < 2^p. Boundaries still satisfy this requirement
405
+ // (even for denormals where the delta can be much more important).
406
+
407
+ const double k1Log10 = 0.30102999566398114; // 1/lg(10)
408
+
409
+ // For doubles len(f) == 53 (don't forget the hidden bit).
410
+ const int kSignificandSize = Double::kSignificandSize;
411
+ double estimate = ceil((exponent + kSignificandSize - 1) * k1Log10 - 1e-10);
412
+ return static_cast<int>(estimate);
413
+ }
414
+
415
+
416
+ // See comments for InitialScaledStartValues.
417
+ static void InitialScaledStartValuesPositiveExponent(
418
+ uint64_t significand, int exponent,
419
+ int estimated_power, bool need_boundary_deltas,
420
+ Bignum* numerator, Bignum* denominator,
421
+ Bignum* delta_minus, Bignum* delta_plus) {
422
+ // A positive exponent implies a positive power.
423
+ ASSERT(estimated_power >= 0);
424
+ // Since the estimated_power is positive we simply multiply the denominator
425
+ // by 10^estimated_power.
426
+
427
+ // numerator = v.
428
+ numerator->AssignUInt64(significand);
429
+ numerator->ShiftLeft(exponent);
430
+ // denominator = 10^estimated_power.
431
+ denominator->AssignPowerUInt16(10, estimated_power);
432
+
433
+ if (need_boundary_deltas) {
434
+ // Introduce a common denominator so that the deltas to the boundaries are
435
+ // integers.
436
+ denominator->ShiftLeft(1);
437
+ numerator->ShiftLeft(1);
438
+ // Let v = f * 2^e, then m+ - v = 1/2 * 2^e; With the common
439
+ // denominator (of 2) delta_plus equals 2^e.
440
+ delta_plus->AssignUInt16(1);
441
+ delta_plus->ShiftLeft(exponent);
442
+ // Same for delta_minus. The adjustments if f == 2^p-1 are done later.
443
+ delta_minus->AssignUInt16(1);
444
+ delta_minus->ShiftLeft(exponent);
445
+ }
446
+ }
447
+
448
+
449
+ // See comments for InitialScaledStartValues
450
+ static void InitialScaledStartValuesNegativeExponentPositivePower(
451
+ uint64_t significand, int exponent,
452
+ int estimated_power, bool need_boundary_deltas,
453
+ Bignum* numerator, Bignum* denominator,
454
+ Bignum* delta_minus, Bignum* delta_plus) {
455
+ // v = f * 2^e with e < 0, and with estimated_power >= 0.
456
+ // This means that e is close to 0 (have a look at how estimated_power is
457
+ // computed).
458
+
459
+ // numerator = significand
460
+ // since v = significand * 2^exponent this is equivalent to
461
+ // numerator = v * / 2^-exponent
462
+ numerator->AssignUInt64(significand);
463
+ // denominator = 10^estimated_power * 2^-exponent (with exponent < 0)
464
+ denominator->AssignPowerUInt16(10, estimated_power);
465
+ denominator->ShiftLeft(-exponent);
466
+
467
+ if (need_boundary_deltas) {
468
+ // Introduce a common denominator so that the deltas to the boundaries are
469
+ // integers.
470
+ denominator->ShiftLeft(1);
471
+ numerator->ShiftLeft(1);
472
+ // Let v = f * 2^e, then m+ - v = 1/2 * 2^e; With the common
473
+ // denominator (of 2) delta_plus equals 2^e.
474
+ // Given that the denominator already includes v's exponent the distance
475
+ // to the boundaries is simply 1.
476
+ delta_plus->AssignUInt16(1);
477
+ // Same for delta_minus. The adjustments if f == 2^p-1 are done later.
478
+ delta_minus->AssignUInt16(1);
479
+ }
480
+ }
481
+
482
+
483
+ // See comments for InitialScaledStartValues
484
+ static void InitialScaledStartValuesNegativeExponentNegativePower(
485
+ uint64_t significand, int exponent,
486
+ int estimated_power, bool need_boundary_deltas,
487
+ Bignum* numerator, Bignum* denominator,
488
+ Bignum* delta_minus, Bignum* delta_plus) {
489
+ // Instead of multiplying the denominator with 10^estimated_power we
490
+ // multiply all values (numerator and deltas) by 10^-estimated_power.
491
+
492
+ // Use numerator as temporary container for power_ten.
493
+ Bignum* power_ten = numerator;
494
+ power_ten->AssignPowerUInt16(10, -estimated_power);
495
+
496
+ if (need_boundary_deltas) {
497
+ // Since power_ten == numerator we must make a copy of 10^estimated_power
498
+ // before we complete the computation of the numerator.
499
+ // delta_plus = delta_minus = 10^estimated_power
500
+ delta_plus->AssignBignum(*power_ten);
501
+ delta_minus->AssignBignum(*power_ten);
502
+ }
503
+
504
+ // numerator = significand * 2 * 10^-estimated_power
505
+ // since v = significand * 2^exponent this is equivalent to
506
+ // numerator = v * 10^-estimated_power * 2 * 2^-exponent.
507
+ // Remember: numerator has been abused as power_ten. So no need to assign it
508
+ // to itself.
509
+ ASSERT(numerator == power_ten);
510
+ numerator->MultiplyByUInt64(significand);
511
+
512
+ // denominator = 2 * 2^-exponent with exponent < 0.
513
+ denominator->AssignUInt16(1);
514
+ denominator->ShiftLeft(-exponent);
515
+
516
+ if (need_boundary_deltas) {
517
+ // Introduce a common denominator so that the deltas to the boundaries are
518
+ // integers.
519
+ numerator->ShiftLeft(1);
520
+ denominator->ShiftLeft(1);
521
+ // With this shift the boundaries have their correct value, since
522
+ // delta_plus = 10^-estimated_power, and
523
+ // delta_minus = 10^-estimated_power.
524
+ // These assignments have been done earlier.
525
+ // The adjustments if f == 2^p-1 (lower boundary is closer) are done later.
526
+ }
527
+ }
528
+
529
+
530
+ // Let v = significand * 2^exponent.
531
+ // Computes v / 10^estimated_power exactly, as a ratio of two bignums, numerator
532
+ // and denominator. The functions GenerateShortestDigits and
533
+ // GenerateCountedDigits will then convert this ratio to its decimal
534
+ // representation d, with the required accuracy.
535
+ // Then d * 10^estimated_power is the representation of v.
536
+ // (Note: the fraction and the estimated_power might get adjusted before
537
+ // generating the decimal representation.)
538
+ //
539
+ // The initial start values consist of:
540
+ // - a scaled numerator: s.t. numerator/denominator == v / 10^estimated_power.
541
+ // - a scaled (common) denominator.
542
+ // optionally (used by GenerateShortestDigits to decide if it has the shortest
543
+ // decimal converting back to v):
544
+ // - v - m-: the distance to the lower boundary.
545
+ // - m+ - v: the distance to the upper boundary.
546
+ //
547
+ // v, m+, m-, and therefore v - m- and m+ - v all share the same denominator.
548
+ //
549
+ // Let ep == estimated_power, then the returned values will satisfy:
550
+ // v / 10^ep = numerator / denominator.
551
+ // v's boundarys m- and m+:
552
+ // m- / 10^ep == v / 10^ep - delta_minus / denominator
553
+ // m+ / 10^ep == v / 10^ep + delta_plus / denominator
554
+ // Or in other words:
555
+ // m- == v - delta_minus * 10^ep / denominator;
556
+ // m+ == v + delta_plus * 10^ep / denominator;
557
+ //
558
+ // Since 10^(k-1) <= v < 10^k (with k == estimated_power)
559
+ // or 10^k <= v < 10^(k+1)
560
+ // we then have 0.1 <= numerator/denominator < 1
561
+ // or 1 <= numerator/denominator < 10
562
+ //
563
+ // It is then easy to kickstart the digit-generation routine.
564
+ //
565
+ // The boundary-deltas are only filled if the mode equals BIGNUM_DTOA_SHORTEST
566
+ // or BIGNUM_DTOA_SHORTEST_SINGLE.
567
+
568
+ static void InitialScaledStartValues(uint64_t significand,
569
+ int exponent,
570
+ bool lower_boundary_is_closer,
571
+ int estimated_power,
572
+ bool need_boundary_deltas,
573
+ Bignum* numerator,
574
+ Bignum* denominator,
575
+ Bignum* delta_minus,
576
+ Bignum* delta_plus) {
577
+ if (exponent >= 0) {
578
+ InitialScaledStartValuesPositiveExponent(
579
+ significand, exponent, estimated_power, need_boundary_deltas,
580
+ numerator, denominator, delta_minus, delta_plus);
581
+ } else if (estimated_power >= 0) {
582
+ InitialScaledStartValuesNegativeExponentPositivePower(
583
+ significand, exponent, estimated_power, need_boundary_deltas,
584
+ numerator, denominator, delta_minus, delta_plus);
585
+ } else {
586
+ InitialScaledStartValuesNegativeExponentNegativePower(
587
+ significand, exponent, estimated_power, need_boundary_deltas,
588
+ numerator, denominator, delta_minus, delta_plus);
589
+ }
590
+
591
+ if (need_boundary_deltas && lower_boundary_is_closer) {
592
+ // The lower boundary is closer at half the distance of "normal" numbers.
593
+ // Increase the common denominator and adapt all but the delta_minus.
594
+ denominator->ShiftLeft(1); // *2
595
+ numerator->ShiftLeft(1); // *2
596
+ delta_plus->ShiftLeft(1); // *2
597
+ }
598
+ }
599
+
600
+
601
+ // This routine multiplies numerator/denominator so that its values lies in the
602
+ // range 1-10. That is after a call to this function we have:
603
+ // 1 <= (numerator + delta_plus) /denominator < 10.
604
+ // Let numerator the input before modification and numerator' the argument
605
+ // after modification, then the output-parameter decimal_point is such that
606
+ // numerator / denominator * 10^estimated_power ==
607
+ // numerator' / denominator' * 10^(decimal_point - 1)
608
+ // In some cases estimated_power was too low, and this is already the case. We
609
+ // then simply adjust the power so that 10^(k-1) <= v < 10^k (with k ==
610
+ // estimated_power) but do not touch the numerator or denominator.
611
+ // Otherwise the routine multiplies the numerator and the deltas by 10.
612
+ static void FixupMultiply10(int estimated_power, bool is_even,
613
+ int* decimal_point,
614
+ Bignum* numerator, Bignum* denominator,
615
+ Bignum* delta_minus, Bignum* delta_plus) {
616
+ bool in_range;
617
+ if (is_even) {
618
+ // For IEEE doubles half-way cases (in decimal system numbers ending with 5)
619
+ // are rounded to the closest floating-point number with even significand.
620
+ in_range = Bignum::PlusCompare(*numerator, *delta_plus, *denominator) >= 0;
621
+ } else {
622
+ in_range = Bignum::PlusCompare(*numerator, *delta_plus, *denominator) > 0;
623
+ }
624
+ if (in_range) {
625
+ // Since numerator + delta_plus >= denominator we already have
626
+ // 1 <= numerator/denominator < 10. Simply update the estimated_power.
627
+ *decimal_point = estimated_power + 1;
628
+ } else {
629
+ *decimal_point = estimated_power;
630
+ numerator->Times10();
631
+ if (Bignum::Equal(*delta_minus, *delta_plus)) {
632
+ delta_minus->Times10();
633
+ delta_plus->AssignBignum(*delta_minus);
634
+ } else {
635
+ delta_minus->Times10();
636
+ delta_plus->Times10();
637
+ }
638
+ }
639
+ }
640
+
641
+ } // namespace double_conversion