X-Git-Url: https://scm.cri.ensmp.fr/git/linpy.git/blobdiff_plain/841943174bb4d3b602e8e055592d8b54d1bb086d..66e41ccd173874b3309e4c24be64c7b6b2ac6298:/pypol/isl.py diff --git a/pypol/isl.py b/pypol/isl.py index 758fb79..32ce305 100644 --- a/pypol/isl.py +++ b/pypol/isl.py @@ -1,267 +1,136 @@ - import ctypes, ctypes.util -import math -import numbers -import operator -import re - -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 +from . import _isl -class Context: - __slots__ = ('_ic') +__all__ = [ + 'Context', + 'BasicSet', +] - 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: +libisl = ctypes.CDLL(ctypes.util.find_library('isl')) - class _ptr(int): - def __new__(cls, iv): - return super().__new__(cls, iv) - def __repr__(self): - return '{}({})'.format(self.__class__.__name__, self) +libisl.isl_printer_get_str.restype = ctypes.c_char_p +libisl.isl_dim_set = _isl.dim_set - _RE_NONFINITE = re.compile( - r'^\s*(?P[-+])?((?PInf(inity)?)|(?PNaN))\s*$', - re.IGNORECASE) - _RE_FRACTION = re.compile(r'^(?P[-+]?\d+)(/(?P\d+))?$') +class IslObject: - __slots__ = ('context', '_iv', '_numerator', '_denominator') + __slots__ = ( + '_ptr', + ) - 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): - def _polymorphic(func): - @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 - - @_polymorphic - def __lt__(self, other): - return bool(libisl.isl_val_lt(self, other)) - - @_polymorphic - def __le__(self, other): - return bool(libisl.isl_val_le(self, other)) - - @_polymorphic - def __gt__(self, other): - return bool(libisl.isl_val_gt(self, other)) + def __init__(self): + ptr = libisl.isl_ctx_alloc() + super().__init__(ptr) - @_polymorphic - 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 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 - 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 - 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 - 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 - 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) + + def constraints(self): + return _isl.basic_set_constraints(self._ptr) + + def _fromisl(self, cls, symbols): + constraints = self.constraints() + equalities = [] + inequalities = [] + co = [] + eq_string = "" + in_string = "" + string = "" + for constraint in constraints: + ls = libisl.isl_basic_set_get_local_space(self) + ctx = libisl.isl_local_space_get_ctx(ls) + p = libisl.isl_printer_to_str(ctx) + if libisl.isl_constraint_is_equality(constraint): #check if equality + constant = libisl.isl_constraint_get_constant_val(constraint) + const = libisl.isl_printer_print_val(p, constant) + const = libisl.isl_printer_get_str(const).decode() + const = int(const) + libisl.isl_printer_free(p) + for symbol in symbols: + p = libisl.isl_printer_to_str(ctx) + dim = symbols.index(symbol) + coefficient = libisl.isl_constraint_get_coefficient_val(constraint, libisl.isl_dim_set, dim) + coeff = libisl.isl_printer_print_val(p, coefficient) + coeff = libisl.isl_printer_get_str(coeff).decode() + coeff = int(coeff) + if coeff!=0: + co.append('{}{}'.format(coeff, symbols[dim])) + for value in co: + string += '{}+'.format(value) + equalities.append('{}{}==0'.format(string, const)) + co = [] + string = '' + libisl.isl_printer_free(p) + else: #same for inequality + constant = libisl.isl_constraint_get_constant_val(constraint) + const = libisl.isl_printer_print_val(p, constant) + const = libisl.isl_printer_get_str(const).decode() + const = int(const) + libisl.isl_printer_free(p) + for symbol in symbols: + p = libisl.isl_printer_to_str(ctx) + dim = symbols.index(symbol) + coefficient = libisl.isl_constraint_get_coefficient_val(constraint, libisl.isl_dim_set, dim) + coeff = libisl.isl_printer_print_val(p, coefficient) + coeff = libisl.isl_printer_get_str(coeff).decode() + coeff = int(coeff) + if coeff!=0: + co.append('{}{}'.format(coeff, symbols[dim])) + for value in co: + string += '{} + '.format(value) + inequalities.append('{}{} <= 0'.format(string, const)) + co = [] + string = "" + libisl.isl_printer_free(p) + + for equations in equalities: + eq_string += ' {}'.format(equations) + eq_strings = eq_string.split() + print(eq_strings) + + for equations in inequalities: + in_string += ', {}'.format(equations) + print(in_string) + if eq_string and in_string: + final = '{}, {}'.format(eq_string, in_string) + elif eq_string != '': + final = '{}'.format(eq_strings) + elif in_string != '' : + final = '{}'.format(in_string) + + + return ('{}({!r})'.format(cls.__name__,final)) +