Source code for crikit.cr.stdnumeric

from crikit.cr.types import Space
from crikit.cr.space_builders import DirectSum
from crikit.cr.map_builders import Callable
from functools import update_wrapper


class Numbers(Space):
    def __init__(self, name, pointclass, compat_classes=()):
        self._name = name
        self._pointclass = pointclass
        self._compat_classes = frozenset(compat_classes + (pointclass,))

    def shape(self):
        return ()

    def __str__(self):
        return self._name

    def point(self, **kwargs):
        return self._pointclass(0)

    def is_point(self, point):
        if isinstance(point, self._compat_classes):
            return True
        return False


class Integers(Numbers):
    def __init__(self, name=None):
        _name = "ZZ(std)" if name is None else name
        super(Integers, self).__init__(_name, int)


ZZ = Integers()  #: Represents the space of integers


class Reals(Numbers):
    def __init__(self, name=None):
        _name = "RR(std)" if name is None else name
        super(Reals, self).__init__(_name, float, (int,))


RR = Reals()  #: Represents the space of real numbers


class Complexs(Numbers):
    def __init__(self, name=None):
        _name = "CC(std)" if name is None else name
        super(Complexs, self).__init__(_name, complex, (int, float))


CC = Complexs()  #: Represents the space of complex numbers


[docs]def type_tuple_to_space(tt): """Converts the given numeric type or tuple of types to a Space using the stdnumeric spaces and DirectSum. If ``tt`` is a tuple, :code:`type_tuple_to_space()` is recursively called on each element of the tuple, and the DirectSum of the result is returned. If ``tt`` is a numeric type, then the corresponding stdnumeric Space is returned. If ``tt`` is a subclass of a numeric type, the name of the returned space will contain the name of that class. Supported numeric types are :class:`int`, :class:`float`, :class:`complex`, or subclasses of those types. Args: tt: a numeric type or arbitrarily nested tuples of numeric types. Returns: Space: the stdnumeric Space corresponding to the given types. Todo: * Use numbers.Integral/Real/Complex to find the corresponding space, """ if isinstance(tt, type): stdnumeric = ( (int, ZZ, Integers, "ZZ"), (float, RR, Reals, "RR"), (complex, CC, Complexs, "CC"), ) for numbers in stdnumeric: if issubclass(tt, numbers[0]): if tt == numbers[0]: return numbers[1] else: return numbers[2](f"{numbers[3]}({tt!s})") raise NotImplementedError elif isinstance(tt, tuple): return DirectSum(*tuple(map(type_tuple_to_space, tt))) else: raise NotImplementedError
[docs]def point_map(source_types, target_types, **kwargs): """Decorates a function to make it a point map (by constructing a Callable instance). Args: source_types: a type tuple representing the source space. target_types: a type tuple representing the target space. **kwargs: passed through to the :class:`~crikit.cr.map_builders.Callable` constructor. Here's example usage for calculating the p-norm of a two-dimensional vector: .. testcode:: from crikit.cr.stdnumeric import point_map @point_map(((float, float), float), float, bare=True) def pnorm_2d(v, p): return (v[0]**p + v[1]**p) ** (1/p) assert pnorm_2d(((1, 2), 1)) == 3 from crikit.cr.types import PointMap from crikit.cr.space_builders import DirectSum from crikit.cr.stdnumeric import RR assert isinstance(pnorm_2d, PointMap) assert pnorm_2d.source == DirectSum(DirectSum(RR, RR), RR) assert pnorm_2d.target == RR """ source_space = type_tuple_to_space(source_types) target_space = type_tuple_to_space(target_types) def point_map_decorator(func): pm = Callable(source_space, target_space, func, **kwargs) return pm return point_map_decorator