X-Git-Url: https://scm.cri.ensmp.fr/git/linpy.git/blobdiff_plain/966727e8d6a1bcbb27dfb1586daa233b006b4fca..b96bc9c75fe5a692898435e8fb12fda27566b1aa:/pypol/isl.py diff --git a/pypol/isl.py b/pypol/isl.py index f1e63dc..ecc32c7 100644 --- a/pypol/isl.py +++ b/pypol/isl.py @@ -1,279 +1,51 @@ -""" -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 math -import numbers -import operator -import re -import functools +from . import _isl -from decimal import Decimal -from fractions import Fraction -from functools import wraps 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: +class IslObject: - __slots__ = ('_ic') + __slots__ = ('_ptr') - def __init__(self): - self._ic = libisl.isl_ctx_alloc() + def __init__(self, ptr): + self._ptr = ptr @property def _as_parameter_(self): - return self._ic - - #comment out so does not delete itself after being created - #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[-+])?((?PInf(inity)?)|(?PNaN))\s*$', - re.IGNORECASE) - - _RE_FRACTION = re.compile(r'^(?P[-+]?\d+)(/(?P\d+))?$') - - __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 - - - @property - def _as_parameter_(self): - return self._iv - - def symbols(self): - s = set() - for constraint in self.constraints(): - s.update(constraint.symbols) - yield from sorted(s) - - def __del__(self): - libisl.isl_val_free(self) - self.context # prevents context from being GC'ed before the value - - @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 + return self._ptr - def __bool__(self): - return not bool(libisl.isl_val_is_zero(self)) - @_polymorphic_method - def __lt__(self, other): - return bool(libisl.isl_val_lt(self, other)) +class Context(IslObject): - @_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): + ptr = libisl.isl_ctx_alloc() + super().__init__(ptr) - @_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)