4dcd4aabf306af401ced69a2684ec26a83fbd043 — Jasper den Ouden 6 months ago 1d6c50e
Stepping substract, Stepping step positive. Bit more testing of intersections, sorting intersections.
M test/sets/general.py => test/sets/general.py +2 -3
@@ 26,10 26,9 @@ def did_inc(*args):
# Compares using the function to calculated sets.
for _n in range(50):
    fr = -30 + 60*random()
    step = randint(-30,30)
    if step == 0: step = 1
    step = randint(1,30)

    sets = [SetRange(fr, fr + 4*random()), SetStepping(randint(-30, 30), step)]
    sets = [SetRange(fr, fr + 4*random()), SetStepping(randint(1, 30), step)]
    sets.append(SetIntersection(sets))  # TODO it doesnt have .random
    for set in sets:
        for k, info in fun_info.items():

M test/sets/intersection.py => test/sets/intersection.py +34 -9
@@ 1,20 1,45 @@

from type_stack_calc.sets.range import SetRange 
from type_stack_calc.sets.stepping import SetStepping
from type_stack_calc.sets.intersection import SetIntersection
from type_stack_calc.sets.range import SetRange as r
from type_stack_calc.sets.stepping import SetStepping as s
from type_stack_calc.sets.intersection import SetIntersection as si
from type_stack_calc.sets.empty import Empty

from type_stack_calc.util.fun_info import fun_info

# Jumps over expect empty.

#print(Intersection(Range(-10, 10), Stepping(-11,2)))
#print(Intersection.cls_absorb(Range(-10, 10), Stepping(-11,20)) == Intersection(9))

assert SetIntersection().ext_absorb(SetRange(-10, 10), SetStepping(-11,20)) == SetIntersection((9,))
assert si().ext_absorb(r(-10, 10), s(-11,20)) == si((9,))

assert si().ext_absorb(r(-10, 10), s(-11,30))[0] is Empty
assert s(0,30).in_set_clamps_hard(1,10) is Empty

def check(a, b, *what):
    a, b = si(sorted(a)), si(sorted(b))
    for name, eq in what:
        eq = si(sorted(eq))  # (im lazy)
        meth_name = f"param_{name}" if name[0]!=':' else name[1:]
        got = getattr(a, meth_name)(b)
        assert got == eq, f"{a} {name} {b}:\n {eq} vs {got}"
        if fun_info[name].commute:  # Try other way round if it commutes.
            got = getattr(b, meth_name)(a)
            assert got == eq, f"{b} {name} {a}:\n {eq} vs {got} (commuted)"

assert SetIntersection().ext_absorb(SetRange(-10, 10), SetStepping(-11,30))[0] is Empty
assert SetStepping(0, 30).set_intersect(SetRange(1,10)) is Empty
assert SetStepping(0,30).in_set_clamps_hard(1,10) is Empty
assert s(0, 30).set_intersect(r(1,10)) is Empty
assert si([r(0,10), s(0,1)]).param_mult(si([r(3,3)])) \
        == si([s(0,3), r(0,30)])
# Range & set versus constant.
check([r(0,10), s(0,1)], [r(3,3)],
      ('mult', [r(0,30), s(0,3)]),
      ('add',  [r(3,13), s(0,1)]),
      ('subtract',  [r(-3,7), s(0,1)]))
# Range & set x 2.
check([s(0,1), r(0,10)], [s(0,2), r(0,10)],
      ('mult', [r(0,100), s(0,2)]),
      ('add',  [r(0,20), s(0,1)]),
      ('subtract',  [r(-10,10), s(0,1)]))

assert SetIntersection([SetRange(0,10), SetStepping(0,1)]).param_mult(SetIntersection([SetRange(3,3)])) == SetIntersection([SetRange(0,30), SetStepping(0,3)])
assert s(0,1).param_mult(r(3,3)) == s(0,3)

assert SetStepping(0,1).param_mult(SetRange(3,3)) == SetStepping(0,3)

M type_stack_calc/sets/intersection.py => type_stack_calc/sets/intersection.py +1 -1
@@ 72,7 72,7 @@ class SetIntersection(tuple):
        if fix_val_fun := getattr(self, 'fix_val', None):
            vals = map(fix_val_fun, vals)

        return type(self)(intersect_absorb(*vals))
        return type(self)(sorted(intersect_absorb(*vals)))

    repr_prep = 'intersect'
    def __repr__(self):

M type_stack_calc/sets/stepping.py => type_stack_calc/sets/stepping.py +8 -5
@@ 21,7 21,7 @@ NOTE: `None` results or omissions of methods often means it turns into a regular
    def __new__(cls, orig, step):
        assert isinstance(orig, int)# TODO support float too? Subdivisions?
        assert isinstance(step, int)
        assert step != 0
        assert step > 0, step
        orig = orig % step  # Simplify the origin.
        return super(SetStepping, cls).__new__(cls, (orig, step))

@@ 32,7 32,7 @@ NOTE: `None` results or omissions of methods often means it turns into a regular
            i += 1
            if i+1 >=len(ints):
                return None
        return type(self)(ints[i], ints[i+1] - ints[i]).union(*ints[i+1:])
        return type(self)(ints[i], abs(ints[i+1] - ints[i])).union(*ints[i+1:])

    def orig(self): return self[0]

@@ 170,12 170,15 @@ NOTE: `None` results or omissions of methods often means it turns into a regular
        return type(self)(orig + y, step)

    stepping_subtract, stepping_add = 2*[stepping_union]  # EXPLAIN
    def num_subtract_disabled(self, y):
        orig, step = self
        return type(self)(orig -y, step)

    def rev_param_substract(self, y):
    def rev_param_subtract(self, y):
        """Just for the case of a constant other end."""
        if isinstance(y, SetRange) and y[0] == y[1]:
            orig, step = self
            return type(self)(orig - y, step)
            return type(self)(orig - y[0], step)

    def num_modulo(self, y):
        orig, step = self

@@ 191,7 194,7 @@ NOTE: `None` results or omissions of methods often means it turns into a regular
    def param_negative(self):
        """Negative value stepping."""
        orig, step = self
        return type(self)(-orig, -step)
        return type(self)(-orig, step)

    def param_abs(self):
        """Figure ability to deal with absolute value."""