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:2275–2334  ·  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

2273@pytest.mark.parametrize('decimal_traits', decimal_type_traits,
2274 ids=lambda v: v.name)
2275def test_cast_float_to_decimal_random(float_ty, decimal_traits):
2276 """
2277 Test float-to-decimal conversion against exactly generated values.
2278 """
2279 r = random.Random(43)
2280 np_float_ty = {
2281 pa.float32(): np.float32,
2282 pa.float64(): np.float64,
2283 }[float_ty]
2284 mantissa_bits = {
2285 pa.float32(): 24,
2286 pa.float64(): 53,
2287 }[float_ty]
2288 float_exp_min, float_exp_max = {
2289 pa.float32(): (-126, 127),
2290 pa.float64(): (-1022, 1023),
2291 }[float_ty]
2292 mantissa_digits = math.floor(math.log10(2**mantissa_bits))
2293 max_precision = decimal_traits.max_precision
2294
2295 # For example, decimal32 <-> float64
2296 if max_precision < mantissa_digits:
2297 mantissa_bits = math.floor(math.log2(10**max_precision))
2298 mantissa_digits = math.floor(math.log10(2**mantissa_bits))
2299
2300 with decimal.localcontext() as ctx:
2301 precision = mantissa_digits
2302 ctx.prec = precision
2303 # The scale must be chosen so as
2304 # 1) it's within bounds for the decimal type
2305 # 2) the floating point exponent is within bounds
2306 min_scale = max(-max_precision,
2307 precision + math.ceil(math.log10(2**float_exp_min)))
2308 max_scale = min(max_precision,
2309 math.floor(math.log10(2**float_exp_max)))
2310 for scale in range(min_scale, max_scale):
2311 decimal_ty = decimal_traits.factory(precision, scale)
2312 # We want to random-generate a float from its mantissa bits
2313 # and exponent, and compute the expected value in the
2314 # decimal domain. The float exponent has to ensure the
2315 # expected value doesn't overflow and doesn't lose precision.
2316 float_exp = (-mantissa_bits +
2317 math.floor(math.log2(10**(precision - scale))))
2318 assert float_exp_min <= float_exp <= float_exp_max
2319 for i in range(5):
2320 mantissa = r.randrange(0, 2**mantissa_bits)
2321 float_val = np.ldexp(np_float_ty(mantissa), float_exp)
2322 assert isinstance(float_val, np_float_ty)
2323 # Make sure we compute the exact expected value and
2324 # round by half-to-even when converting to the expected precision.
2325 if float_exp >= 0:
2326 expected = decimal.Decimal(mantissa) * 2**float_exp
2327 else:
2328 expected = decimal.Decimal(mantissa) / 2**-float_exp
2329 expected_as_int = round(expected.scaleb(scale))
2330 actual = pc.cast(
2331 pa.scalar(float_val, type=float_ty), decimal_ty).as_py()
2332 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