@@ 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():
@@ 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)
@@ 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:])
@property
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."""