@@ -308,6 +308,128 @@ func RyuFixed(d *decimalSlice, mant uint64, exp int, prec int, flt *floatInfo) {
308
308
return
309
309
}
310
310
311
+ func RyuFromDecimal (mant uint64 , exp int , flt * floatInfo ) (fbits uint64 , ovf , ok bool ) {
312
+ // Conversion from decimal to binary floating-point
313
+ // can be achieved by reusing the same building blocks
314
+ // as the Ryū algorithm.
315
+ //
316
+ // Given a decimal mantissa, we can multiply by the requested
317
+ // power of ten using the same routines. The 64 bit result
318
+ // is guaranteed to be correctly truncated (floored), when
319
+ // the decimal mantissa fits in 55 bits.
320
+ //
321
+ // This covers 16-digit mantissas, and a few 17-digits values.
322
+
323
+ bitlen := bits .Len64 (mant )
324
+ if bitlen > 55 {
325
+ return 0 , false , false // cannot handle values that large.
326
+ }
327
+ // Shift mantissa to be exactly 55 bits.
328
+ mant <<= uint (55 - bitlen )
329
+ e2 := bitlen - 55
330
+
331
+ // multiply by a power of 10. It is required to know
332
+ // whether the computation is exact.
333
+ var pow * extfloat128 // a representation of 10^q
334
+ switch {
335
+ case exp > 309 :
336
+ return 0x7ff << 52 , true , true
337
+ case exp < - 342 :
338
+ return 0 , false , true
339
+ case exp > 0 :
340
+ pow = & RyuPowersOfTen [exp ]
341
+ case exp == 0 :
342
+ // no multiply
343
+ case exp < 0 :
344
+ pow = & RyuInvPowersOfTen [- exp ]
345
+ }
346
+ // Is it an exact computation?
347
+ exact := false
348
+ switch {
349
+ case exp > 55 :
350
+ // large positive powers of ten are not exact
351
+ case 54 >= exp && exp >= 0 :
352
+ exact = true
353
+ case 0 > exp && exp >= - 25 :
354
+ // division by a power of ten might be exact
355
+ // if mantissas are multiples of 5
356
+ if divisibleByPower5 (mant , - exp ) {
357
+ exact = true
358
+ }
359
+ default :
360
+ // division by 10^25 cannot be exact
361
+ // as 5^25 has 59 bits.
362
+ }
363
+
364
+ // Compute Floor(x*10^q)
365
+ var di uint64
366
+ var d0 bool
367
+ if exp == 0 {
368
+ di , d0 = mant , true
369
+ exact = true
370
+ } else {
371
+ di , d0 = ryuMultiply (mant , pow .Hi , pow .Lo )
372
+ e2 += pow .Exp + 64 + 55
373
+ }
374
+ // If computation was an exact division, lower bits must be ignored.
375
+ if exp < 0 && exact {
376
+ d0 = true
377
+ }
378
+ // Is exponent too low? Shrink mantissa for denormals.
379
+ blen := bits .Len64 (di )
380
+ e2 += blen - 1
381
+ extra := uint (blen - 53 ) // number of lower bits to remove
382
+ if e2 < flt .bias + 1 {
383
+ extra += uint (flt .bias + 1 - e2 )
384
+ e2 = flt .bias + 1
385
+ }
386
+ if extra > uint (blen ) {
387
+ return 0.0 , false , true
388
+ }
389
+ // Compute correct rounding.
390
+ extramask := uint64 (1 << extra - 1 )
391
+ di , dfrac := di >> extra , di & extramask
392
+ roundUp := false
393
+ if exact {
394
+ // If we computed an exact product, d + 1/2
395
+ // should round to d+1 if 'd' is odd.
396
+ roundUp = dfrac > 1 << (extra - 1 ) ||
397
+ (dfrac == 1 << (extra - 1 ) && ! d0 ) ||
398
+ (dfrac == 1 << (extra - 1 ) && d0 && di & 1 == 1 )
399
+ } else {
400
+ // otherwise, d+1/2 always rounds up because
401
+ // we truncated below.
402
+ roundUp = dfrac >> (extra - 1 ) == 1
403
+ }
404
+ if dfrac != 0 {
405
+ d0 = false
406
+ }
407
+ if roundUp {
408
+ di ++
409
+ }
410
+
411
+ // Rounding might have added a bit; shift down.
412
+ if di == 2 << flt .mantbits {
413
+ di >>= 1
414
+ e2 ++
415
+ }
416
+
417
+ // Infinities.
418
+ if e2 - flt .bias >= 1 << flt .expbits - 1 {
419
+ // ±Inf
420
+ di = 0
421
+ e2 = 1 << flt .expbits - 1 + flt .bias
422
+ ovf = true
423
+ } else if di & (1 << flt .mantbits ) == 0 {
424
+ // Denormalized?
425
+ e2 = flt .bias
426
+ }
427
+ // Assemble bits.
428
+ fbits = di & (uint64 (1 )<< flt .mantbits - 1 )
429
+ fbits |= uint64 ((e2 - flt .bias )& (1 << flt .expbits - 1 )) << flt .mantbits
430
+ return fbits , ovf , true
431
+ }
432
+
311
433
func divisibleByPower5 (m uint64 , k int ) bool {
312
434
for i := 0 ; i < k ; i ++ {
313
435
a , b := m / 5 , m % 5
@@ -1142,4 +1264,28 @@ var RyuInvPowersOfTen = [...]extfloat128{
1142
1264
{Hi : 0xf712b443bbd52b7b , Lo : 0xa5e9ec7501d523e5 , Exp : - 1181 },
1143
1265
{Hi : 0xc5a890362fddbc62 , Lo : 0xeb2189f734aa831e , Exp : - 1184 },
1144
1266
{Hi : 0x9e20735e8cb16382 , Lo : 0x55b46e5f5d5535b1 , Exp : - 1187 },
1267
+ {Hi : 0xfd00b897478238d0 , Lo : 0x8920b098955522b5 , Exp : - 1191 },
1268
+ {Hi : 0xca66fa129f9b60a6 , Lo : 0xd41a26e077774ef7 , Exp : - 1194 },
1269
+ {Hi : 0xa1ebfb4219491a1f , Lo : 0x1014ebe6c5f90bf9 , Exp : - 1197 },
1270
+ {Hi : 0x818995ce7aa0e1b2 , Lo : 0x7343efebd1940994 , Exp : - 1200 },
1271
+ {Hi : 0xcf42894a5dce35ea , Lo : 0x52064cac828675ba , Exp : - 1204 },
1272
+ {Hi : 0xa5ced43b7e3e9188 , Lo : 0x419ea3bd35385e2e , Exp : - 1207 },
1273
+ {Hi : 0x84a57695fe98746d , Lo : 0x014bb630f7604b58 , Exp : - 1210 },
1274
+ {Hi : 0xd43bf0effdc0ba48 , Lo : 0x0212bd1b2566def3 , Exp : - 1214 },
1275
+ {Hi : 0xa9c98d8ccb009506 , Lo : 0x680efdaf511f18c3 , Exp : - 1217 },
1276
+ {Hi : 0x87d4713d6f33aa6b , Lo : 0x8672648c40e5ad69 , Exp : - 1220 },
1277
+ {Hi : 0xd953e8624b85dd78 , Lo : 0xd71d6dad34a2af0e , Exp : - 1224 },
1278
+ {Hi : 0xaddcb9e83c6b1793 , Lo : 0xdf4abe242a1bbf3e , Exp : - 1227 },
1279
+ {Hi : 0x8b16fb203055ac76 , Lo : 0x4c3bcb5021afcc32 , Exp : - 1230 },
1280
+ {Hi : 0xde8b2b66b3bc4723 , Lo : 0xad2c788035e61383 , Exp : - 1234 },
1281
+ {Hi : 0xb208ef855c969f4f , Lo : 0xbdbd2d335e51a936 , Exp : - 1237 },
1282
+ {Hi : 0x8e6d8c6ab0787f72 , Lo : 0xfe30f0f5e50e20f8 , Exp : - 1240 },
1283
+ {Hi : 0xe3e27a444d8d98b7 , Lo : 0xfd1b1b2308169b26 , Exp : - 1244 },
1284
+ {Hi : 0xb64ec836a47146f9 , Lo : 0x9748e2826cdee285 , Exp : - 1247 },
1285
+ {Hi : 0x91d8a02bb6c10594 , Lo : 0x79071b9b8a4be86a , Exp : - 1250 },
1286
+ {Hi : 0xe95a99df8ace6f53 , Lo : 0xf4d82c2c107973dd , Exp : - 1254 },
1287
+ {Hi : 0xbaaee17fa23ebf76 , Lo : 0x5d79bcf00d2df64a , Exp : - 1257 },
1288
+ {Hi : 0x9558b4661b6565f8 , Lo : 0x4ac7ca59a424c508 , Exp : - 1260 },
1289
+ {Hi : 0xeef453d6923bd65a , Lo : 0x113faa2906a13b40 , Exp : - 1264 },
1290
+ {Hi : 0xbf29dcaba82fdeae , Lo : 0x7432ee873880fc34 , Exp : - 1267 },
1145
1291
}
0 commit comments