MCPcopy Create free account
hub / github.com/apache/arrow / test_cast_float_to_decimal_random

Function test_cast_float_to_decimal_random

python/pyarrow/tests/test_compute.py:2421–2480  ·  view source on GitHub ↗

Test float-to-decimal conversion against exactly generated values.

(float_ty, decimal_traits)

Source from the content-addressed store, hash-verified

2419@pytest.mark.parametrize('decimal_traits', decimal_type_traits,
2420 ids=lambda v: v.name)
2421def test_cast_float_to_decimal_random(float_ty, decimal_traits):
2422 """
2423 Test float-to-decimal conversion against exactly generated values.
2424 """
2425 r = random.Random(43)
2426 np_float_ty = {
2427 pa.float32(): np.float32,
2428 pa.float64(): np.float64,
2429 }[float_ty]
2430 mantissa_bits = {
2431 pa.float32(): 24,
2432 pa.float64(): 53,
2433 }[float_ty]
2434 float_exp_min, float_exp_max = {
2435 pa.float32(): (-126, 127),
2436 pa.float64(): (-1022, 1023),
2437 }[float_ty]
2438 mantissa_digits = math.floor(math.log10(2**mantissa_bits))
2439 max_precision = decimal_traits.max_precision
2440
2441 # For example, decimal32 <-> float64
2442 if max_precision < mantissa_digits:
2443 mantissa_bits = math.floor(math.log2(10**max_precision))
2444 mantissa_digits = math.floor(math.log10(2**mantissa_bits))
2445
2446 with decimal.localcontext() as ctx:
2447 precision = mantissa_digits
2448 ctx.prec = precision
2449 # The scale must be chosen so as
2450 # 1) it's within bounds for the decimal type
2451 # 2) the floating point exponent is within bounds
2452 min_scale = max(-max_precision,
2453 precision + math.ceil(math.log10(2**float_exp_min)))
2454 max_scale = min(max_precision,
2455 math.floor(math.log10(2**float_exp_max)))
2456 for scale in range(min_scale, max_scale):
2457 decimal_ty = decimal_traits.factory(precision, scale)
2458 # We want to random-generate a float from its mantissa bits
2459 # and exponent, and compute the expected value in the
2460 # decimal domain. The float exponent has to ensure the
2461 # expected value doesn't overflow and doesn't lose precision.
2462 float_exp = (-mantissa_bits +
2463 math.floor(math.log2(10**(precision - scale))))
2464 assert float_exp_min <= float_exp <= float_exp_max
2465 for i in range(5):
2466 mantissa = r.randrange(0, 2**mantissa_bits)
2467 float_val = np.ldexp(np_float_ty(mantissa), float_exp)
2468 assert isinstance(float_val, np_float_ty)
2469 # Make sure we compute the exact expected value and
2470 # round by half-to-even when converting to the expected precision.
2471 if float_exp >= 0:
2472 expected = decimal.Decimal(mantissa) * 2**float_exp
2473 else:
2474 expected = decimal.Decimal(mantissa) / 2**-float_exp
2475 expected_as_int = round(expected.scaleb(scale))
2476 actual = pc.cast(
2477 pa.scalar(float_val, type=float_ty), decimal_ty).as_py()
2478 actual_as_int = round(actual.scaleb(scale))

Callers

nothing calls this directly

Calls 5

as_pyMethod · 0.80
RandomMethod · 0.45
DecimalMethod · 0.45
castMethod · 0.45
scalarMethod · 0.45

Tested by

no test coverage detected