def clamp(x, xmin, xmax): """Constrain a value to lie between two further values, element-wise. The returned value is computed as `min(max(x, xmin), xmax)`. The arguments can be scalars or :class:`~taichi.Matrix`, as long as they can be broadcasted to a common shape. Args: x (:mod:`~taichi.types.primitive_types`, :class:`~taichi.Matrix`): Specify the value to constrain. y (:mod:`~taichi.types.primitive_types`, :class:`~taichi.Matrix`): Specify the lower end of the range into which to constrain `x`. a (:mod:`~taichi.types.primitive_types`, :class:`~taichi.Matrix`): Specify the upper end of the range into which to constrain `x`. Returns: The value of `x` constrained to the range `xmin` to `xmax`. Example:: >>> v = ti.Vector([0, 0.5, 1.0, 1.5]) >>> ti.clamp(v, 0.5, 1.0) [0.5, 0.5, 1.0, 1.0] >>> x = ti.Matrix([[0, 1], [-2, 2]], ti.f32) >>> y = ti.Matrix([[1, 2], [1, 2]], ti.f32) >>> ti.clamp(x, 0.5, y) [[0.5, 1.0], [0.5, 2.0]] """ return min(xmax, max(xmin, x))
def __init__(self, *args): args = list(args) for i, arg in enumerate(args): if not isinstance(arg, collections.abc.Sequence): args[i] = (0, arg) if len(args[i]) != 2: raise TaichiSyntaxError( "Every argument of ndrange should be a scalar or a tuple/list like (begin, end)" ) args[i] = (args[i][0], ops.max(args[i][0], args[i][1])) for arg in args: for bound in arg: if not isinstance(bound, int) and not ( isinstance(bound, Expr) and is_integral(bound.ptr.get_ret_type())): raise TaichiTypeError( "Every argument of ndrange should be an integer scalar or a tuple/list of (int, int)" ) self.bounds = args self.dimensions = [None] * len(args) for i, bound in enumerate(self.bounds): self.dimensions[i] = bound[1] - bound[0] self.acc_dimensions = self.dimensions.copy() for i in reversed(range(len(self.bounds) - 1)): self.acc_dimensions[ i] = self.acc_dimensions[i] * self.acc_dimensions[i + 1] if len(self.acc_dimensions ) == 0: # for the empty case, e.g. ti.ndrange() self.acc_dimensions = [1]