File: test_float_utils.py

package info (click to toggle)
python-hypothesis 6.138.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 15,272 kB
  • sloc: python: 62,853; ruby: 1,107; sh: 253; makefile: 41; javascript: 6
file content (108 lines) | stat: -rw-r--r-- 3,861 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# This file is part of Hypothesis, which may be found at
# https://github.com/HypothesisWorks/hypothesis/
#
# Copyright the Hypothesis Authors.
# Individual contributors are listed in AUTHORS.rst and the git log.
#
# This Source Code Form is subject to the terms of the Mozilla Public License,
# v. 2.0. If a copy of the MPL was not distributed with this file, You can
# obtain one at https://mozilla.org/MPL/2.0/.

import math
from sys import float_info

import pytest

from hypothesis import example, given, strategies as st
from hypothesis.internal.conjecture.choice import choice_equal, choice_permitted
from hypothesis.internal.conjecture.provider_conformance import float_constraints
from hypothesis.internal.floats import (
    count_between_floats,
    make_float_clamper,
    next_down,
    next_up,
    sign_aware_lte,
)

from tests.conjecture.common import float_constr


def test_can_handle_straddling_zero():
    assert count_between_floats(-0.0, 0.0) == 2


@pytest.mark.parametrize(
    "func,val",
    [
        (next_up, math.nan),
        (next_up, math.inf),
        (next_up, -0.0),
        (next_down, math.nan),
        (next_down, -math.inf),
        (next_down, 0.0),
    ],
)
def test_next_float_equal(func, val):
    if math.isnan(val):
        assert math.isnan(func(val))
    else:
        assert func(val) == val


# exponent comparisons:
@example(float_constr(1, float_info.max), 0)
@example(float_constr(1, float_info.max), 1)
@example(float_constr(1, float_info.max), 10)
@example(float_constr(1, float_info.max), float_info.max)
@example(float_constr(1, float_info.max), math.inf)
# mantissa comparisons:
@example(float_constr(100.0001, 100.0003), 100.0001)
@example(float_constr(100.0001, 100.0003), 100.0002)
@example(float_constr(100.0001, 100.0003), 100.0003)
@example(float_constr(100.0001, 100.0003, allow_nan=False), math.nan)
@example(float_constr(0, 10, allow_nan=False), math.nan)
@example(float_constr(0, 10, allow_nan=True), math.nan)
# the branch coverage of resampling in the "out of range of smallest magnitude" case
# relies on randomness from the mantissa. try a few different values.
@example(float_constr(-4, -1, smallest_nonzero_magnitude=4), 4)
@example(float_constr(-4, -1, smallest_nonzero_magnitude=4), 5)
@example(float_constr(-4, -1, smallest_nonzero_magnitude=4), 6)
@example(float_constr(1, 4, smallest_nonzero_magnitude=4), -4)
@example(float_constr(1, 4, smallest_nonzero_magnitude=4), -5)
@example(float_constr(1, 4, smallest_nonzero_magnitude=4), -6)
@example(float_constr(-5e-324, -0.0), 3.0)
@example(float_constr(0.0, 0.0), -0.0)
@example(float_constr(-0.0, -0.0), 0.0)
@given(float_constraints(), st.floats())
def test_float_clamper(constraints, input_value):
    min_value = constraints["min_value"]
    max_value = constraints["max_value"]
    allow_nan = constraints["allow_nan"]
    smallest_nonzero_magnitude = constraints["smallest_nonzero_magnitude"]
    clamper = make_float_clamper(
        min_value,
        max_value,
        smallest_nonzero_magnitude=smallest_nonzero_magnitude,
        allow_nan=allow_nan,
    )
    clamped = clamper(input_value)
    if math.isnan(clamped):
        # we should only clamp to nan if nans are allowed.
        assert allow_nan
    else:
        # otherwise, we should have clamped to something in the permitted range.
        assert sign_aware_lte(min_value, clamped)
        assert sign_aware_lte(clamped, max_value)

    # if input_value was permitted in the first place, then the clamped value should
    # be the same as the input value.
    if choice_permitted(
        input_value,
        {
            "min_value": min_value,
            "max_value": max_value,
            "allow_nan": allow_nan,
            "smallest_nonzero_magnitude": smallest_nonzero_magnitude,
        },
    ):
        assert choice_equal(input_value, clamped)