+"""
+note: for islpy
+isl format: basic set: ("{[x, y] : x >= 0 and x < 5 and y >= 0 and y < x+4 }")
+"""
import ctypes, ctypes.util
+import functools
import math
import numbers
import operator
import re
-import functools
-from decimal import Decimal
-from fractions import Fraction
-from functools import wraps
+from . import _isl
libisl = ctypes.CDLL(ctypes.util.find_library('isl'))
libisl.isl_printer_get_str.restype = ctypes.c_char_p
+libisl.isl_dim_set = _isl.isl_dim_set
-def _polymorphic_method(func):
- @functools.wraps(func)
- def wrapper(self, other):
- if isinstance(other, Value):
- return func(self, other)
- if isinstance(other, numbers.Rational):
- other = Value(self.context, other)
- return func(self, other)
- raise TypeError('operand should be a Value or a Rational')
- return wrapper
-
-class Context:
-
- __slots__ = ('_ic')
-
- def __init__(self):
- self._ic = libisl.isl_ctx_alloc()
-
- @property
- def _as_parameter_(self):
- return self._ic
-
- def __del__(self):
- libisl.isl_ctx_free(self)
-
- def __eq__(self, other):
- if not isinstance(other, Context):
- return False
- return self._ic == other._ic
-
-
-class Value:
-
- class _ptr(int):
- def __new__(cls, iv):
- return super().__new__(cls, iv)
- def __repr__(self):
- return '{}({})'.format(self.__class__.__name__, self)
- _RE_NONFINITE = re.compile(
- r'^\s*(?P<sign>[-+])?((?P<inf>Inf(inity)?)|(?P<nan>NaN))\s*$',
- re.IGNORECASE)
+class IslObject:
- _RE_FRACTION = re.compile(r'^(?P<num>[-+]?\d+)(/(?P<den>\d+))?$')
+ __slots__ = ('_ptr')
- __slots__ = ('context', '_iv', '_numerator', '_denominator')
-
- def __new__(cls, context, numerator=0, denominator=None):
- self = super().__new__(cls)
- if not isinstance(context, Context):
- raise TypeError('first argument should be a context')
- self.context = context
- if isinstance(numerator, cls._ptr):
- assert denominator is None
- self._iv = numerator
- if libisl.isl_val_is_rat(self):
- # retrieve numerator and denominator as strings to avoid integer
- # overflows
- ip = libisl.isl_printer_to_str(self.context)
- ip = libisl.isl_printer_print_val(ip, self)
- string = libisl.isl_printer_get_str(ip).decode()
- libisl.isl_printer_free(ip)
- m = self._RE_FRACTION.match(string)
- assert m is not None
- self._numerator = int(m.group('num'))
- self._denominator = int(m.group('den')) if m.group('den') else 1
- else:
- self._numerator = None
- self._denominator = None
- return self
- if isinstance(numerator, str) and denominator is None:
- m = self._RE_NONFINITE.match(numerator)
- if m is not None:
- self._numerator = None
- self._denominator = None
- if m.group('inf'):
- if m.group('sign') == '-':
- self._iv = libisl.isl_val_neginfty(context)
- else:
- self._iv = libisl.isl_val_infty(context)
- else:
- assert m.group('nan')
- self._iv = libisl.isl_val_nan(context)
- return self
- try:
- frac = Fraction(numerator, denominator)
- except ValueError:
- raise ValueError('invalid literal for {}: {!r}'.format(
- cls.__name__, numerator))
- self._numerator = frac.numerator
- self._denominator = frac.denominator
- # values passed as strings to avoid integer overflows
- if frac.denominator == 1:
- numerator = str(frac.numerator).encode()
- self._iv = libisl.isl_val_read_from_str(context, numerator)
- else:
- numerator = str(frac.numerator).encode()
- numerator = libisl.isl_val_read_from_str(context, numerator)
- denominator = str(frac.denominator).encode()
- denominator = libisl.isl_val_read_from_str(context, denominator)
- self._iv = libisl.isl_val_div(numerator, denominator)
- return self
+ def __init__(self, ptr):
+ self._ptr = ptr
@property
def _as_parameter_(self):
- return self._iv
-
- def __del__(self):
- libisl.isl_val_free(self)
- self.context # prevents context from being GC'ed before the value
+ return self._ptr
- @property
- def numerator(self):
- if self._numerator is None:
- raise ValueError('not a rational number')
- return self._numerator
-
- @property
- def denominator(self):
- if self._denominator is None:
- raise ValueError('not a rational number')
- return self._denominator
- def __bool__(self):
- return not bool(libisl.isl_val_is_zero(self))
+class Context(IslObject):
- @_polymorphic_method
- def __lt__(self, other):
- return bool(libisl.isl_val_lt(self, other))
-
- @_polymorphic_method
- def __le__(self, other):
- return bool(libisl.isl_val_le(self, other))
-
- @_polymorphic_method
- def __gt__(self, other):
- return bool(libisl.isl_val_gt(self, other))
+ def __init__(self):
+ self._ptr = libisl.isl_ctx_alloc()
- @_polymorphic_method
- def __ge__(self, other):
- return bool(libisl.isl_val_ge(self, other))
+ #comment out so does not delete itself after being created
+ #def __del__(self):
+ # libisl.isl_ctx_free(self)
- @_polymorphic_method
def __eq__(self, other):
- return bool(libisl.isl_val_eq(self, other))
-
- # __ne__ is not implemented, ISL semantics does not match Python's on
- # nan != nan
-
- def __abs__(self):
- val = libisl.isl_val_copy(self)
- val = libisl.isl_val_abs(val)
- return self.__class__(self.context, self._ptr(val))
-
- def __pos__(self):
- return self
-
- def __neg__(self):
- val = libisl.isl_val_copy(self)
- val = libisl.isl_val_neg(val)
- return self.__class__(self.context, self._ptr(val))
-
- def __floor__(self):
- val = libisl.isl_val_copy(self)
- val = libisl.isl_val_floor(val)
- return self.__class__(self.context, self._ptr(val))
-
- def __ceil__(self):
- val = libisl.isl_val_copy(self)
- val = libisl.isl_val_ceil(val)
- return self.__class__(self.context, self._ptr(val))
-
- def __trunc__(self):
- val = libisl.isl_val_copy(self)
- val = libisl.isl_val_trunc(val)
- return self.__class__(self.context, self._ptr(val))
-
- @_polymorphic_method
- def __add__(self, other):
- val1 = libisl.isl_val_copy(self)
- val2 = libisl.isl_val_copy(other)
- val = libisl.isl_val_add(val1, val2)
- return self.__class__(self.context, self._ptr(val))
-
- __radd__ = __add__
-
- @_polymorphic_method
- def __sub__(self, other):
- val1 = libisl.isl_val_copy(self)
- val2 = libisl.isl_val_copy(other)
- val = libisl.isl_val_sub(val1, val2)
- return self.__class__(self.context, self._ptr(val))
-
- __rsub__ = __sub__
-
- @_polymorphic_method
- def __mul__(self, other):
- val1 = libisl.isl_val_copy(self)
- val2 = libisl.isl_val_copy(other)
- val = libisl.isl_val_mul(val1, val2)
- return self.__class__(self.context, self._ptr(val))
-
- __rmul__ = __mul__
-
- @_polymorphic_method
- def __truediv__(self, other):
- val1 = libisl.isl_val_copy(self)
- val2 = libisl.isl_val_copy(other)
- val = libisl.isl_val_div(val1, val2)
- return self.__class__(self.context, self._ptr(val))
-
- __rtruediv__ = __truediv__
-
- def __float__(self):
- if libisl.isl_val_is_rat(self):
- return self.numerator / self.denominator
- elif libisl.isl_val_is_infty(self):
- return float('inf')
- elif libisl.isl_val_is_neginfty(self):
- return float('-inf')
- else:
- assert libisl.isl_val_is_nan(self)
- return float('nan')
-
- def is_finite(self):
- return bool(libisl.isl_val_is_rat(self))
+ if not isinstance(other, Context):
+ return False
+ return self._ptr == other._ptr
- def is_infinite(self):
- return bool(libisl.isl_val_is_infty(self) or
- libisl.isl_val_is_neginfty(self))
- def is_nan(self):
- return bool(libisl.isl_val_is_nan(self))
+class BasicSet(IslObject):
def __str__(self):
- if libisl.isl_val_is_rat(self):
- if self.denominator == 1:
- return '{}'.format(self.numerator)
- else:
- return '{}/{}'.format(self.numerator, self.denominator)
- elif libisl.isl_val_is_infty(self):
- return 'Infinity'
- elif libisl.isl_val_is_neginfty(self):
- return '-Infinity'
- else:
- assert libisl.isl_val_is_nan(self)
- return 'NaN'
+ ls = libisl.isl_basic_set_get_local_space(self)
+ ctx = libisl.isl_local_space_get_ctx(ls)
+ p = libisl.isl_printer_to_str(ctx)
+ p = libisl.isl_printer_print_basic_set(p, self)
+ string = libisl.isl_printer_get_str(p).decode()
+ return string
- def __repr__(self):
- return '{}({!r})'.format(self.__class__.__name__, str(self))
+ def __del__(self):
+ libisl.isl_basic_set_free(self)