示例#1
0
    def inverse(self):
        """The inverse of a matrix.

        Note:
            The matrix dimension should be less than or equal to 4.

        Returns:
            The inverse of a matrix.

        Raises:
            Exception: Inversions of matrices with sizes >= 5 are not supported.

        """
        assert self.n == self.m, 'Only square matrices are invertible'
        if self.n == 1:
            return Matrix([1 / self(0, 0)])
        elif self.n == 2:
            inv_det = impl.expr_init(1.0 / self.determinant())
            # Discussion: https://github.com/taichi-dev/taichi/pull/943#issuecomment-626344323
            return inv_det * Matrix([[self(1, 1), -self(0, 1)],
                                     [-self(1, 0), self(0, 0)]]).variable()
        elif self.n == 3:
            n = 3
            inv_determinant = impl.expr_init(1.0 / self.determinant())
            entries = [[0] * n for _ in range(n)]

            def E(x, y):
                return self(x % n, y % n)

            for i in range(n):
                for j in range(n):
                    entries[j][i] = impl.expr_init(
                        inv_determinant * (E(i + 1, j + 1) * E(i + 2, j + 2) -
                                           E(i + 2, j + 1) * E(i + 1, j + 2)))
            return Matrix(entries)
        elif self.n == 4:
            n = 4
            inv_determinant = impl.expr_init(1.0 / self.determinant())
            entries = [[0] * n for _ in range(n)]

            def E(x, y):
                return self(x % n, y % n)

            for i in range(n):
                for j in range(n):
                    entries[j][i] = impl.expr_init(
                        inv_determinant * (-1)**(i + j) *
                        ((E(i + 1, j + 1) *
                          (E(i + 2, j + 2) * E(i + 3, j + 3) -
                           E(i + 3, j + 2) * E(i + 2, j + 3)) -
                          E(i + 2, j + 1) *
                          (E(i + 1, j + 2) * E(i + 3, j + 3) -
                           E(i + 3, j + 2) * E(i + 1, j + 3)) +
                          E(i + 3, j + 1) *
                          (E(i + 1, j + 2) * E(i + 2, j + 3) -
                           E(i + 2, j + 2) * E(i + 1, j + 3)))))
            return Matrix(entries)
        else:
            raise Exception(
                "Inversions of matrices with sizes >= 5 are not supported")
示例#2
0
    def build_assign_annotated(ctx, target, value, is_static_assign,
                               annotation):
        """Build an annotated assginment like this: target: annotation = value.

         Args:
            ctx (ast_builder_utils.BuilderContext): The builder context.
            target (ast.Name): A variable name. `target.id` holds the name as
            a string.
            annotation: A type we hope to assign to the target
            value: A node representing the value.
            is_static_assign: A boolean value indicating whether this is a static assignment
        """
        is_local = isinstance(target, ast.Name)
        anno = impl.expr_init(annotation)
        if is_static_assign:
            raise TaichiSyntaxError(
                "Static assign cannot be used on annotated assignment")
        if is_local and not ctx.is_var_declared(target.id):
            var = ti_ops.cast(value, anno)
            var = impl.expr_init(var)
            ctx.create_variable(target.id, var)
        else:
            var = build_stmt(ctx, target)
            if var.ptr.get_ret_type() != anno:
                raise TaichiSyntaxError(
                    "Static assign cannot have type overloading")
            var.assign(value)
        return var
示例#3
0
文件: linalg.py 项目: zxgtz/taichi
def svd3d(A, dt, iters=None):
    assert A.n == 3 and A.m == 3
    inputs = tuple([e.ptr for e in A.entries])
    assert dt in [ti.f32, ti.f64]
    if iters is None:
        if dt == ti.f32:
            iters = 5
        else:
            iters = 8
    if dt == ti.f32:
        rets = _ti_core.sifakis_svd_f32(*inputs, iters)
    else:
        rets = _ti_core.sifakis_svd_f64(*inputs, iters)
    assert len(rets) == 21
    U_entries = rets[:9]
    V_entries = rets[9:18]
    sig_entries = rets[18:]
    U = expr_init(ti.Matrix.zero(dt, 3, 3))
    V = expr_init(ti.Matrix.zero(dt, 3, 3))
    sigma = expr_init(ti.Matrix.zero(dt, 3, 3))
    for i in range(3):
        for j in range(3):
            U(i, j).assign(U_entries[i * 3 + j])
            V(i, j).assign(V_entries[i * 3 + j])
        sigma(i, i).assign(sig_entries[i])
    return U, sigma, V
示例#4
0
 def build_ndrange_for(ctx, node):
     with ctx.variable_scope_guard():
         ndrange_var = impl.expr_init(build_stmt(ctx, node.iter))
         ndrange_begin = ti_ops.cast(expr.Expr(0), primitive_types.i32)
         ndrange_end = ti_ops.cast(
             expr.Expr(impl.subscript(ndrange_var.acc_dimensions, 0)),
             primitive_types.i32)
         ndrange_loop_var = expr.Expr(_ti_core.make_id_expr(''))
         _ti_core.begin_frontend_range_for(ndrange_loop_var.ptr,
                                           ndrange_begin.ptr,
                                           ndrange_end.ptr)
         I = impl.expr_init(ndrange_loop_var)
         targets = ASTTransformer.get_for_loop_targets(node)
         for i, target in enumerate(targets):
             if i + 1 < len(targets):
                 target_tmp = impl.expr_init(
                     I // ndrange_var.acc_dimensions[i + 1])
             else:
                 target_tmp = impl.expr_init(I)
             ctx.create_variable(
                 target,
                 impl.expr_init(target_tmp + impl.subscript(
                     impl.subscript(ndrange_var.bounds, i), 0)))
             if i + 1 < len(targets):
                 I.assign(I -
                          target_tmp * ndrange_var.acc_dimensions[i + 1])
         build_stmts(ctx, node.body)
         _ti_core.end_frontend_range_for()
     return None
示例#5
0
 def store(self, index, value):
     args_group = ()
     if self.num_dims == 1:
         args_group = impl.make_expr_group(index.x, value.r, value.g,
                                           value.b, value.a)
     elif self.num_dims == 2:
         args_group = impl.make_expr_group(index.x, index.y, value.r,
                                           value.g, value.b, value.a)
     elif self.num_dims == 3:
         args_group = impl.make_expr_group(index.x, index.y, index.z,
                                           value.r, value.g, value.b,
                                           value.a)
     impl.expr_init(
         _ti_core.make_texture_op_expr(_ti_core.TextureOpType.kStore,
                                       self.ptr_expr, args_group))
示例#6
0
文件: ops.py 项目: kokizzu/taichi
def atomic_sub(x, y):
    """Atomically subtract `x` by `y`, store the result in `x`,
    and return the old value of `x`.

    `x` must be a writable target, constant expressions or scalars
    are not allowed.

    Args:
        x, y (Union[:mod:`~taichi.types.primitive_types`, :class:`~taichi.Matrix`]): \
            The input.

    Returns:
        The old value of `x`.

    Example::

        >>> @ti.kernel
        >>> def test():
        >>>     x = ti.Vector([0, 0, 0])
        >>>     y = ti.Vector([1, 2, 3])
        >>>     z = ti.atomic_sub(x, y)
        >>>     print(x)  # [-1, -2, -3]  the new value of x
        >>>     print(z)  # [0, 0, 0], the old value of x
        >>>
        >>>     ti.atomic_sub(1, x)  # will raise TaichiSyntaxError
    """
    return impl.expr_init(
        expr.Expr(_ti_core.expr_atomic_sub(x.ptr, y.ptr), tb=stack_info()))
示例#7
0
    def build_IfExp(ctx, node):
        build_stmt(ctx, node.test)
        build_stmt(ctx, node.body)
        build_stmt(ctx, node.orelse)

        if is_taichi_class(node.test.ptr) or is_taichi_class(
                node.body.ptr) or is_taichi_class(node.orelse.ptr):
            node.ptr = ti_ops.select(node.test.ptr, node.body.ptr,
                                     node.orelse.ptr)
            return node.ptr

        is_static_if = (ASTTransformer.get_decorator(ctx,
                                                     node.test) == "static")

        if is_static_if:
            if node.test.ptr:
                node.ptr = build_stmt(ctx, node.body)
            else:
                node.ptr = build_stmt(ctx, node.orelse)
            return node.ptr

        val = impl.expr_init(None)

        impl.begin_frontend_if(node.test.ptr)
        _ti_core.begin_frontend_if_true()
        val.assign(node.body.ptr)
        _ti_core.pop_scope()
        _ti_core.begin_frontend_if_false()
        val.assign(node.orelse.ptr)
        _ti_core.pop_scope()

        node.ptr = val
        return node.ptr
示例#8
0
文件: ops.py 项目: kokizzu/taichi
def atomic_xor(x, y):
    """Atomically compute the bit-wise XOR of `x` and `y`, element-wise.
    Store the result in `x`, and return the old value of `x`.

    `x` must be a writable target, constant expressions or scalars
    are not allowed.

    Args:
        x, y (Union[:mod:`~taichi.types.primitive_types`, :class:`~taichi.Matrix`]): \
            The input. When both are matrices they must have the same shape.

    Returns:
        The old value of `x`.

    Example::

        >>> @ti.kernel
        >>> def test():
        >>>     x = ti.Vector([-1, 0, 1])
        >>>     y = ti.Vector([1, 2, 3])
        >>>     z = ti.atomic_xor(x, y)
        >>>     print(x)  # [-2, 2, 2]  the new value of x
        >>>     print(z)  # [-1, 0, 1], the old value of x
        >>>
        >>>     ti.atomic_xor(1, x)  # will raise TaichiSyntaxError
    """
    return impl.expr_init(
        expr.Expr(_ti_core.expr_atomic_bit_xor(x.ptr, y.ptr), tb=stack_info()))
示例#9
0
    def build_assign_basic(ctx, target, value, is_static_assign):
        """Build basic assginment like this: target = value.

         Args:
            ctx (ast_builder_utils.BuilderContext): The builder context.
            target (ast.Name): A variable name. `target.id` holds the name as
            a string.
            value: A node representing the value.
            is_static_assign: A boolean value indicating whether this is a static assignment
        """
        is_local = isinstance(target, ast.Name)
        if is_static_assign:
            if not is_local:
                raise TaichiSyntaxError(
                    "Static assign cannot be used on elements in arrays")
            ctx.create_variable(target.id, value)
            var = value
        elif is_local and not ctx.is_var_declared(target.id):
            var = impl.expr_init(value)
            ctx.create_variable(target.id, var)
        else:
            var = build_stmt(ctx, target)
            try:
                var.assign(value)
            except AttributeError:
                raise TaichiSyntaxError(
                    f"Variable '{unparse(target).strip()}' cannot be assigned. Maybe it is not a Taichi object?"
                )
        return var
示例#10
0
文件: ops.py 项目: kokizzu/taichi
def atomic_max(x, y):
    """Atomically compute the maximum of `x` and `y`, element-wise.
    Store the result in `x`, and return the old value of `x`.

    `x` must be a writable target, constant expressions or scalars
    are not allowed.

    Args:
        x, y (Union[:mod:`~taichi.types.primitive_types`, :class:`~taichi.Matrix`]): \
            The input.

    Returns:
        The old value of `x`.

    Example::

        >>> @ti.kernel
        >>> def test():
        >>>     x = 1
        >>>     y = 2
        >>>     z = ti.atomic_max(x, y)
        >>>     print(x)  # 2  the new value of x
        >>>     print(z)  # 1, the old value of x
        >>>
        >>>     ti.atomic_max(1, x)  # will raise TaichiSyntaxError
    """
    return impl.expr_init(
        expr.Expr(_ti_core.expr_atomic_max(x.ptr, y.ptr), tb=stack_info()))
示例#11
0
    def determinant(a):
        if a.n == 2 and a.m == 2:
            return a(0, 0) * a(1, 1) - a(0, 1) * a(1, 0)
        elif a.n == 3 and a.m == 3:
            return a(0, 0) * (a(1, 1) * a(2, 2) - a(2, 1) * a(1, 2)) - a(
                1, 0) * (a(0, 1) * a(2, 2) - a(2, 1) * a(0, 2)) + a(
                    2, 0) * (a(0, 1) * a(1, 2) - a(1, 1) * a(0, 2))
        elif a.n == 4 and a.m == 4:
            n = 4

            def E(x, y):
                return a(x % n, y % n)

            det = impl.expr_init(0.0)
            for i in range(4):
                det = det + (-1.0)**i * (
                    a(i, 0) *
                    (E(i + 1, 1) *
                     (E(i + 2, 2) * E(i + 3, 3) - E(i + 3, 2) * E(i + 2, 3)) -
                     E(i + 2, 1) *
                     (E(i + 1, 2) * E(i + 3, 3) - E(i + 3, 2) * E(i + 1, 3)) +
                     E(i + 3, 1) *
                     (E(i + 1, 2) * E(i + 2, 3) - E(i + 2, 2) * E(i + 1, 3))))
            return det
        else:
            raise Exception(
                "Determinants of matrices with sizes >= 5 are not supported")
示例#12
0
def solve(A, b, dt=None):
    """Solve a matrix using Gauss elimination method.

    Args:
        A (ti.Matrix(n, n)): input nxn matrix `A`.
        b (ti.Vector(n, 1)): input nx1 vector `b`.
        dt (DataType): The datatype for the `A` and `b`.

    Returns:
        x (ti.Vector(n, 1)): the solution of Ax=b.
    """
    assert A.n == A.m, "Only sqaure matrix is supported"
    assert A.n >= 2 and A.n <= 3, "Only 2D and 3D matrices are supported"
    assert A.m == b.n, "Matrix and Vector dimension dismatch"
    if dt is None:
        dt = impl.get_runtime().default_fp
    nrow, ncol = static(A.n, A.n + 1)
    Ab = expr_init(Matrix.zero(dt, nrow, ncol))
    lhs = tuple([e.ptr for e in A.entries])
    rhs = tuple([e.ptr for e in b.entries])
    for i in range(nrow):
        for j in range(nrow):
            Ab(i, j)._assign(lhs[nrow * i + j])
    for i in range(nrow):
        Ab(i, nrow)._assign(rhs[i])
    if A.n == 2:
        return _gauss_elimination_2x2(Ab, dt)
    if A.n == 3:
        return _gauss_elimination_3x3(Ab, dt)
    raise Exception("Solver only supports 2D and 3D matrices.")
示例#13
0
 def variable(self):
     ret = self.copy()
     ret.entries = {
         k: impl.expr_init(v) if isinstance(v,
                                            (numbers.Number,
                                             expr.Expr)) else v.variable()
         for k, v in ret.items
     }
     return ret
示例#14
0
def append(node, indices, val):
    """Append a value `val` to a SNode `node` at index `indices`.

    Args:
        node (:class:`~taichi.SNode`): Input SNode.
        indices (Union[int, :class:`~taichi.Vector`]): the indices to visit.
        val (:mod:`~taichi.types`): the data to be appended.
    """
    a = impl.expr_init(
        _ti_core.insert_append(node._snode.ptr, expr.make_expr_group(indices),
                               expr.Expr(val).ptr))
    return a
示例#15
0
def random(dtype=float):
    """The random function.

    Args:
        dtype (DataType): Type of the random variable.

    Returns:
        A random variable whose type is `dtype`.
    """
    dtype = cook_dtype(dtype)
    x = expr.Expr(_ti_core.make_rand_expr(dtype))
    return impl.expr_init(x)
示例#16
0
def svd3d(A, dt, iters=None):
    """Perform singular value decomposition (A=USV^T) for 3x3 matrix.

    Mathematical concept refers to https://en.wikipedia.org/wiki/Singular_value_decomposition.

    Args:
        A (ti.Matrix(3, 3)): input 3x3 matrix `A`.
        dt (DataType): date type of elements in matrix `A`, typically accepts ti.f32 or ti.f64.
        iters (int): iteration number to control algorithm precision.

    Returns:
        Decomposed 3x3 matrices `U`, 'S' and `V`.
    """
    assert A.n == 3 and A.m == 3
    inputs = tuple([e.ptr for e in A.entries])
    assert dt in [f32, f64]
    if iters is None:
        if dt == f32:
            iters = 5
        else:
            iters = 8
    if dt == f32:
        rets = get_runtime().prog.current_ast_builder().sifakis_svd_f32(
            *inputs, iters)
    else:
        rets = get_runtime().prog.current_ast_builder().sifakis_svd_f64(
            *inputs, iters)
    assert len(rets) == 21
    U_entries = rets[:9]
    V_entries = rets[9:18]
    sig_entries = rets[18:]
    U = expr_init(Matrix.zero(dt, 3, 3))
    V = expr_init(Matrix.zero(dt, 3, 3))
    sigma = expr_init(Matrix.zero(dt, 3, 3))
    for i in range(3):
        for j in range(3):
            U(i, j)._assign(U_entries[i * 3 + j])
            V(i, j)._assign(V_entries[i * 3 + j])
        sigma(i, i)._assign(sig_entries[i])
    return U, sigma, V
示例#17
0
    def build_grouped_ndrange_for(ctx, node):
        with ctx.variable_scope_guard():
            ndrange_var = impl.expr_init(build_stmt(ctx, node.iter.args[0]))
            ndrange_begin = ti_ops.cast(expr.Expr(0), primitive_types.i32)
            ndrange_end = ti_ops.cast(
                expr.Expr(impl.subscript(ndrange_var.acc_dimensions, 0)),
                primitive_types.i32)
            ndrange_loop_var = expr.Expr(_ti_core.make_id_expr(''))
            _ti_core.begin_frontend_range_for(ndrange_loop_var.ptr,
                                              ndrange_begin.ptr,
                                              ndrange_end.ptr)

            targets = ASTTransformer.get_for_loop_targets(node)
            if len(targets) != 1:
                raise TaichiSyntaxError(
                    f"Group for should have 1 loop target, found {len(targets)}"
                )
            target = targets[0]
            target_var = impl.expr_init(
                matrix.Vector([0] * len(ndrange_var.dimensions),
                              dt=primitive_types.i32))
            ctx.create_variable(target, target_var)
            I = impl.expr_init(ndrange_loop_var)
            for i in range(len(ndrange_var.dimensions)):
                if i + 1 < len(ndrange_var.dimensions):
                    target_tmp = I // ndrange_var.acc_dimensions[i + 1]
                else:
                    target_tmp = I
                impl.subscript(target_var,
                               i).assign(target_tmp + ndrange_var.bounds[i][0])
                if i + 1 < len(ndrange_var.dimensions):
                    I.assign(I -
                             target_tmp * ndrange_var.acc_dimensions[i + 1])
            build_stmts(ctx, node.body)
            _ti_core.end_frontend_range_for()
        return None
示例#18
0
    def build_Assign(ctx, node):
        build_stmt(ctx, node.value)

        is_static_assign = isinstance(
            node.value, ast.Call) and node.value.func.ptr is impl.static

        # Keep all generated assign statements and compose single one at last.
        # The variable is introduced to support chained assignments.
        # Ref https://github.com/taichi-dev/taichi/issues/2659.
        values = node.value.ptr if is_static_assign else impl.expr_init(
            node.value.ptr)

        for node_target in node.targets:
            ASTTransformer.build_assign_unpack(ctx, node_target, values,
                                               is_static_assign)
        return None
示例#19
0
文件: struct.py 项目: kokizzu/taichi
 def __init__(self, *args, **kwargs):
     # converts lists to matrices and dicts to structs
     if len(args) == 1 and kwargs == {} and isinstance(args[0], dict):
         self.entries = args[0]
     elif len(args) == 0:
         self.entries = kwargs
     else:
         raise TaichiSyntaxError(
             "Custom structs need to be initialized using either dictionary or keyword arguments"
         )
     for k, v in self.entries.items():
         if isinstance(v, (list, tuple)):
             v = Matrix(v)
         if isinstance(v, dict):
             v = Struct(v)
         self.entries[k] = v if in_python_scope() else impl.expr_init(v)
     self._register_members()
示例#20
0
    def build_short_circuit_and(ast_builder, operands):
        if len(operands) == 1:
            return operands[0].ptr

        val = impl.expr_init(None)
        lhs = operands[0].ptr
        impl.begin_frontend_if(ast_builder, lhs)

        ast_builder.begin_frontend_if_true()
        rhs = ASTTransformer.build_short_circuit_and(ast_builder, operands[1:])
        val.assign(rhs)
        ast_builder.pop_scope()

        ast_builder.begin_frontend_if_false()
        val.assign(0)
        ast_builder.pop_scope()

        return val
示例#21
0
    def build_short_circuit_or(operands):
        if len(operands) == 1:
            return operands[0].ptr

        val = impl.expr_init(None)
        lhs = operands[0].ptr
        impl.begin_frontend_if(lhs)

        _ti_core.begin_frontend_if_true()
        val.assign(1)
        _ti_core.pop_scope()

        _ti_core.begin_frontend_if_false()
        rhs = ASTTransformer.build_short_circuit_or(operands[1:])
        val.assign(rhs)
        _ti_core.pop_scope()

        return val
示例#22
0
    def determinant(a):
        """Get the determinant of a matrix.

        Note:
            The matrix dimension should be less than or equal to 4.

        Returns:
            The determinant of a matrix.

        Raises:
            Exception: Determinants of matrices with sizes >= 5 are not supported.

        """
        if a.n == 2 and a.m == 2:
            return a(0, 0) * a(1, 1) - a(0, 1) * a(1, 0)
        elif a.n == 3 and a.m == 3:
            return a(0, 0) * (a(1, 1) * a(2, 2) - a(2, 1) * a(1, 2)) - a(
                1, 0) * (a(0, 1) * a(2, 2) - a(2, 1) * a(0, 2)) + a(
                    2, 0) * (a(0, 1) * a(1, 2) - a(1, 1) * a(0, 2))
        elif a.n == 4 and a.m == 4:
            n = 4

            def E(x, y):
                return a(x % n, y % n)

            det = impl.expr_init(0.0)
            for i in range(4):
                det = det + (-1.0)**i * (
                    a(i, 0) *
                    (E(i + 1, 1) *
                     (E(i + 2, 2) * E(i + 3, 3) - E(i + 3, 2) * E(i + 2, 3)) -
                     E(i + 2, 1) *
                     (E(i + 1, 2) * E(i + 3, 3) - E(i + 3, 2) * E(i + 1, 3)) +
                     E(i + 3, 1) *
                     (E(i + 1, 2) * E(i + 2, 3) - E(i + 2, 2) * E(i + 1, 3))))
            return det
        else:
            raise Exception(
                "Determinants of matrices with sizes >= 5 are not supported")
示例#23
0
    def build_IfExp(ctx, node):
        build_stmt(ctx, node.test)
        build_stmt(ctx, node.body)
        build_stmt(ctx, node.orelse)

        if is_taichi_class(node.test.ptr) or is_taichi_class(
                node.body.ptr) or is_taichi_class(node.orelse.ptr):
            node.ptr = ti_ops.select(node.test.ptr, node.body.ptr,
                                     node.orelse.ptr)
            warnings.warn_explicit(
                'Using conditional expression for element-wise select operation on '
                'Taichi vectors/matrices is deprecated. '
                'Please use "ti.select" instead.', DeprecationWarning,
                ctx.file, node.lineno + ctx.lineno_offset)
            return node.ptr

        is_static_if = (ASTTransformer.get_decorator(ctx,
                                                     node.test) == "static")

        if is_static_if:
            if node.test.ptr:
                node.ptr = build_stmt(ctx, node.body)
            else:
                node.ptr = build_stmt(ctx, node.orelse)
            return node.ptr

        val = impl.expr_init(None)

        impl.begin_frontend_if(ctx.ast_builder, node.test.ptr)
        ctx.ast_builder.begin_frontend_if_true()
        val.assign(node.body.ptr)
        ctx.ast_builder.pop_scope()
        ctx.ast_builder.begin_frontend_if_false()
        val.assign(node.orelse.ptr)
        ctx.ast_builder.pop_scope()

        node.ptr = val
        return node.ptr
示例#24
0
文件: ops.py 项目: kokizzu/taichi
def random(dtype=float):
    """Return a single random float/integer according to the specified data type.
    Must be called in taichi scope.

    If the required `dtype` is float type, this function returns a random number
    sampled from the uniform distribution in the half-open interval [0, 1).

    For integer types this function returns a random integer in the
    half-open interval [0, 2^32) if a 32-bit integer is required,
    or a random integer in the half-open interval [0, 2^64) if a
    64-bit integer is required.

    Args:
        dtype (:mod:`~taichi.types.primitive_types`): Type of the required random value.

    Returns:
        A random value with type `dtype`.

    Example::

        >>> @ti.kernel
        >>> def test():
        >>>     x = ti.random(float)
        >>>     print(x)  # 0.090257
        >>>
        >>>     y = ti.random(ti.f64)
        >>>     print(y)  # 0.716101627301
        >>>
        >>>     i = ti.random(ti.i32)
        >>>     print(i)  # -963722261
        >>>
        >>>     j = ti.random(ti.i64)
        >>>     print(j)  # 73412986184350777
    """
    dtype = cook_dtype(dtype)
    x = expr.Expr(_ti_core.make_rand_expr(dtype))
    return impl.expr_init(x)
示例#25
0
 def variable(self):
     ret = self.copy()
     ret.entries = [impl.expr_init(e) for e in ret.entries]
     return ret
示例#26
0
def append(l, indices, val):
    a = impl.expr_init(
        _ti_core.insert_append(l.snode.ptr, expr.make_expr_group(indices),
                               expr.Expr(val).ptr))
    return a
示例#27
0
def atomic_xor(a, b):
    return impl.expr_init(
        expr.Expr(_ti_core.expr_atomic_bit_xor(a.ptr, b.ptr), tb=stack_info()))
示例#28
0
文件: ops.py 项目: zxgtz/taichi
def random(dtype=float):
    dtype = cook_dtype(dtype)
    x = Expr(_ti_core.make_rand_expr(dtype))
    return impl.expr_init(x)
示例#29
0
文件: ops.py 项目: zxgtz/taichi
def atomic_max(a, b):
    return impl.expr_init(
        Expr(_ti_core.expr_atomic_max(a.ptr, b.ptr), tb=stack_info()))
示例#30
0
    def __init__(self,
                 n=1,
                 m=1,
                 dt=None,
                 shape=None,
                 offset=None,
                 empty=False,
                 layout=None,
                 needs_grad=False,
                 keep_raw=False,
                 rows=None,
                 cols=None):
        self.grad = None

        # construct from rows or cols (deprecated)
        if rows is not None or cols is not None:
            warning(
                f"ti.Matrix(rows=[...]) or ti.Matrix(cols=[...]) is deprecated, use ti.Matrix.rows([...]) or ti.Matrix.cols([...]) instead.",
                DeprecationWarning,
                stacklevel=2)
            if rows is not None and cols is not None:
                raise Exception("cannot specify both rows and columns")
            self.dt = dt
            mat = Matrix.cols(cols) if cols is not None else Matrix.rows(rows)
            self.n = mat.n
            self.m = mat.m
            self.entries = mat.entries
            return

        elif empty == True:
            warning(
                f"ti.Matrix(n, m, empty=True) is deprecated, use ti.Matrix.empty(n, m) instead",
                DeprecationWarning,
                stacklevel=2)
            self.dt = dt
            self.entries = [[None] * m for _ in range(n)]
            return

        elif isinstance(n, (list, tuple, np.ndarray)):
            if len(n) == 0:
                mat = []
            elif isinstance(n[0], Matrix):
                raise Exception(
                    'cols/rows required when using list of vectors')
            elif not isinstance(n[0], Iterable):
                if impl.inside_kernel():
                    # wrap potential constants with Expr
                    if keep_raw:
                        mat = [list([x]) for x in n]
                    else:
                        mat = [list([expr.Expr(x)]) for x in n]
                else:
                    mat = [[x] for x in n]
            else:
                mat = [list(r) for r in n]
            self.n = len(mat)
            if len(mat) > 0:
                self.m = len(mat[0])
            else:
                self.m = 1
            self.entries = [x for row in mat for x in row]

        else:
            if dt is None:
                # create a local matrix with specific (n, m)
                self.entries = [impl.expr_init(None) for i in range(n * m)]
                self.n = n
                self.m = m
            else:
                # construct global matrix (deprecated)
                warning(
                    "Declaring global matrices using `ti.Matrix(n, m, dt, shape)` is deprecated, "
                    "use `ti.Matrix.field(n, m, dtype, shape)` instead",
                    DeprecationWarning,
                    stacklevel=2)
                mat = Matrix.field(n=n,
                                   m=m,
                                   dtype=dt,
                                   shape=shape,
                                   offset=offset,
                                   needs_grad=needs_grad,
                                   layout=layout)
                self.n = mat.n
                self.m = mat.m
                self.entries = mat.entries
                self.grad = mat.grad

        if self.n * self.m > 32:
            warning(
                f'Taichi matrices/vectors with {self.n}x{self.m} > 32 entries are not suggested.'
                ' Matrices/vectors will be automatically unrolled at compile-time for performance.'
                ' So the compilation time could be extremely long if the matrix size is too big.'
                ' You may use a field to store a large matrix like this, e.g.:\n'
                f'    x = ti.field(ti.f32, ({self.n}, {self.m})).\n'
                ' See https://taichi.readthedocs.io/en/stable/tensor_matrix.html#matrix-size'
                ' for more details.',
                UserWarning,
                stacklevel=2)