Source code for hikari.utility.interval

import numpy as np


[docs] class Interval: """ A class handling [A, B] line segments and numpy operations on them. The following magic methods have been implemented for `Interval`: - creation using `Interval(A, B)` syntax (if `A == B`, represents a point) - comparison operations with numbers (True if holds for the whole Interval) - arithmetic operations, which act element-wise for left and right edge - access methods: `A == Interval(A, B)[0] == Interval(A, B).left` - container methods: 5 and 6.2 are `in Interval(5, 7)`, but 7. might not be """ # CREATION METHODS def __init__(self, left, right): self.left = min(left, right) self.right = max(left, right) # COMPARISON METHODS
[docs] def __eq__(self, other): return self.left == other.left and self.right == other.right
[docs] def __lt__(self, other): return self.right < other
[docs] def __gt__(self, other): return self.left > other
[docs] def __le__(self, other): return self.right <= other
[docs] def __ge__(self, other): return self.left >= other
# UNARY OPERATIONS
[docs] def __pos__(self): return self
[docs] def __neg__(self): return Interval(-self.right, -self.left)
# ARITHMETIC METHODS
[docs] def __add__(self, other): return Interval(self.left + other, self.right + other)
[docs] def __sub__(self, other): return Interval(self.left - other, self.right - other)
[docs] def __mul__(self, other): return Interval(self.left * other, self.right * other)
[docs] def __truediv__(self, other): return Interval(self.left / other, self.right / other)
# REPRESENTATION METHODS
[docs] def __str__(self): return f'[{self.left}, {self.right}]'
[docs] def __repr__(self): return f'Interval({self.left}, {self.right})'
# CONTAINER METHODS
[docs] def __iter__(self): yield self.left yield self.right
[docs] def __getitem__(self, key): return [self.left, self.right][key]
[docs] def __setitem__(self, key, value): new_limits = [self.left, self.right] new_limits[key] = value self.left, self.right = new_limits
[docs] def __contains__(self, item): return self.left <= self._min(item) and self._max(item) <= self.right
[docs] def __len__(self): return 2
[docs] @staticmethod def _min(item): """Recursively returns minimum of args if possible, otherwise args""" try: return min(item) except TypeError: return item
[docs] @staticmethod def _max(item): """Recursively returns maximum of args if possible, otherwise args""" try: return max(item) except TypeError: return item
[docs] def arange(self, step=1): """ Return a 1D-list of values from left to right every step :param step: spacing between adjacent values, default 1. :type step: int or float :return: array of values from left to right (including right) every step :rtype: np.array """ epsilon = step * 1e-7 size = 1 + int((self.right - self.left + epsilon) / step) return np.array([self.left + step * i for i in range(size)])
[docs] def comb_with(self, *others, step=1): """ Return combinations of self.arange(step) with every other.arange(step) :param others: interval or iterable of intervals to comb self with :type others: Interval or tuple or list :param step: spacing between adjacent values, default 1. :type step: int or float :return: array of all combinations found in numpy.meshgrid every step :rtype: np.array """ arrays = [self.arange(step)] + [other.arange(step) for other in others] return np.array(np.meshgrid(*arrays)).reshape(len(arrays), -1)
[docs] def mesh_with(self, *others, step=1): """ Return a numpy.mesh of self.arange(step) with every other.arange(step) :param others: interval or iterable of intervals to mesh self with :type others: Interval or tuple or list :param step: spacing between adjacent values, default 1. :type step: int or float :return: array of values meshed by numpy.meshgrid every step :rtype: np.array """ arrays = [self.arange(step)] + [other.arange(step) for other in others] return np.meshgrid(*arrays)