Exemple #1
0
    def inverse(self):
        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(self))
            return inv_det * Matrix([[self(1, 1), -self(0, 1)],
                                     [-self(1, 0), self(0, 0)]])
        elif self.n == 3:
            n = 3
            import taichi as ti
            inv_determinant = ti.expr_init(1.0 / ti.determinant(self))
            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] = ti.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)
        else:
            raise Exception(
                "Inversions of matrices with sizes >= 4 are not supported")
    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 = ti.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.cast(value, anno)
            var = ti.expr_init(var)
            ctx.create_variable(target.id, var)
        else:
            var = target.ptr
            if var.ptr.get_ret_type() != anno:
                raise TaichiSyntaxError(
                    "Static assign cannot have type overloading")
            var.assign(value)
        return var
Exemple #3
0
    def build_grouped_ndrange_for(ctx, node):
        with ctx.variable_scope_guard():
            ndrange_var = ti.expr_init(build_stmt(ctx, node.iter.args[0]).ptr)
            ndrange_begin = ti.cast(ti.Expr(0), ti.i32)
            ndrange_end = ti.cast(
                ti.Expr(ti.subscript(ndrange_var.acc_dimensions, 0)), ti.i32)
            ndrange_loop_var = ti.Expr(ti.core.make_id_expr(''))
            ti.core.begin_frontend_range_for(ndrange_loop_var.ptr,
                                             ndrange_begin.ptr,
                                             ndrange_end.ptr)

            targets = IRBuilder.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 = ti.expr_init(
                ti.Vector([0] * len(ndrange_var.dimensions), dt=ti.i32))
            ctx.create_variable(target, target_var)
            I = ti.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
                ti.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])
            node.body = build_stmts(ctx, node.body)
            ti.core.end_frontend_range_for()
        return node
Exemple #4
0
 def build_ndrange_for(ctx, node):
     with ctx.variable_scope_guard():
         ndrange_var = ti.expr_init(build_stmt(ctx, node.iter).ptr)
         ndrange_begin = ti.cast(ti.Expr(0), ti.i32)
         ndrange_end = ti.cast(
             ti.Expr(ti.subscript(ndrange_var.acc_dimensions, 0)), ti.i32)
         ndrange_loop_var = ti.Expr(ti.core.make_id_expr(''))
         ti.core.begin_frontend_range_for(ndrange_loop_var.ptr,
                                          ndrange_begin.ptr,
                                          ndrange_end.ptr)
         I = ti.expr_init(ndrange_loop_var)
         targets = IRBuilder.get_for_loop_targets(node)
         for i, target in enumerate(targets):
             if i + 1 < len(targets):
                 target_tmp = ti.expr_init(
                     I // ndrange_var.acc_dimensions[i + 1])
             else:
                 target_tmp = ti.expr_init(I)
             ctx.create_variable(
                 target,
                 ti.expr_init(
                     target_tmp +
                     ti.subscript(ti.subscript(ndrange_var.bounds, i), 0)))
             if i + 1 < len(targets):
                 I.assign(I -
                          target_tmp * ndrange_var.acc_dimensions[i + 1])
         node.body = build_stmts(ctx, node.body)
         ti.core.end_frontend_range_for()
     return node
Exemple #5
0
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 = ti.expr_init(ti.Matrix.zero(dt, 3, 3))
    V = ti.expr_init(ti.Matrix.zero(dt, 3, 3))
    sigma = ti.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
Exemple #6
0
def pow(self, power):
    import taichi as ti
    if not isinstance(power, int):
        return raw_pow(self, power)
    if power == 0:
        # TODO: remove the hack, use {Expr,Matrix}.dup().fill(1)
        # also note that this can be solved by #940
        return self * 0 + Expr(1)

    negative = power < 0
    # Why not simply use `power = abs(power)`?
    # Because `abs` is overrided by the `ti.abs` above.
    if negative:
        power = -power

    tmp = self
    ret = None
    while power:
        if power & 1:
            if ret is None:
                ret = tmp
            else:
                ret = ti.expr_init(ret * tmp)
        tmp = ti.expr_init(tmp * tmp)
        power >>= 1

    if negative:
        return 1 / ret
    else:
        return ret
Exemple #7
0
    def inverse(self):
        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
            import taichi as ti
            inv_determinant = ti.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] = ti.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
            import taichi as ti
            inv_determinant = ti.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] = ti.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")
Exemple #8
0
    def build_IfExp(ctx, node):
        node.test = build_stmt(ctx, node.test)
        node.body = build_stmt(ctx, node.body)
        node.orelse = build_stmt(ctx, node.orelse)

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

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

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

        val = ti.expr_init(None)

        ti.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
    def build_IfExp(ctx, node):
        build_stmt(ctx, node.test)
        build_stmt(ctx, node.body)
        build_stmt(ctx, node.orelse)

        if ti.is_taichi_class(node.test.ptr) or ti.is_taichi_class(
                node.body.ptr) or ti.is_taichi_class(node.orelse.ptr):
            node.ptr = ti.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 = ti.expr_init(None)

        ti.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
Exemple #10
0
def _vector_getattr(self, key):
    ret = []
    stk = []
    for k in key:
        sgn = 0
        i = 0
        if k != '_':
            sgn = 1
            i = 'xyzw'.find(k)
            if i == -1:
                sgn = -1
                i = 'XYZW'.find(k)
                if i == -1:
                    break

        stk.append((i, sgn))

    else:
        for i, sgn in stk:
            if ti.inside_kernel():
                t = self.subscript(i) * sgn
                ret.append(ti.expr_init(t))
            else:
                t = self[i] * sgn
                ret.append(t)

        return ti.Vector(ret)

    _taichi_skip_traceback = 1
    raise AttributeError(f"'Matrix' object has no attribute {key}")
Exemple #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:
            import taichi as ti
            n = 4

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

            det = ti.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")
Exemple #12
0
 def __pow__(self, power, modulo=None):
   import taichi as ti
   if not isinstance(power, int) or abs(power) > 100:
     return Expr(taichi_lang_core.expr_pow(self.ptr, Expr(power).ptr))
   if power == 0:
     return Expr(1)
   negative = power < 0
   power = abs(power)
   tmp = self
   ret = None
   while power:
     if power & 1:
       if ret is None:
         ret = tmp
       else:
         ret = ti.expr_init(ret * tmp)
     tmp = ti.expr_init(tmp * tmp)
     power >>= 1
   if negative:
     return 1 / ret
   else:
     return ret
Exemple #13
0
 def __pow__(self, power, modulo=None):
     import taichi as ti
     if ti.is_taichi_class(power):
         return power.element_wise_binary(lambda x, y: pow(y, x), self)
     if not isinstance(power, int) or abs(power) > 100:
         return Expr(taichi_lang_core.expr_pow(self.ptr, Expr(power).ptr))
     if power == 0:
         return Expr(1)
     negative = power < 0
     power = abs(power)
     tmp = self
     ret = None
     while power:
         if power & 1:
             if ret is None:
                 ret = tmp
             else:
                 ret = ti.expr_init(ret * tmp)
         tmp = ti.expr_init(tmp * tmp)
         power >>= 1
     if negative:
         return 1 / ret
     else:
         return ret
Exemple #14
0
    def build_assign_basic(ctx, target, value):
        """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_local = isinstance(target, ast.Name)
        if is_local and not ctx.is_var_declared(target.id):
            ctx.create_variable(target.id, ti.expr_init(value))
        else:
            var = target.ptr
            var.assign(value)
Exemple #15
0
 def polygonise(self, triangles: ti.template()):
     numOftriangle = 0;
     cubeIndex = 0;
     vertlist = [ti.expr_init(ti.Vector.zero(float, 3)) for t in range(12)]  # 保存等值面与立方体各边相交的坐标
     # 确定那个顶点位于等值面内部
     if (grid.val[0] < 1): cubeIndex |= 1;
     if (grid.val[1] < 1): cubeIndex |= 2;
     if (grid.val[2] < 1): cubeIndex |= 4;
     if (grid.val[3] < 1): cubeIndex |= 8;
     if (grid.val[4] < 1): cubeIndex |= 16;
     if (grid.val[5] < 1): cubeIndex |= 32;
     if (grid.val[6] < 1): cubeIndex |= 64;
     if (grid.val[7] < 1): cubeIndex |= 128;
     # 异常:立方体所有顶点都在或者都不在等值面内部
     if (self.edgeTable[cubeIndex] != 0):
         # 确定等值面与立方体交点坐标
         if (edgeTable[cubeIndex] & 1):
             vertlist[0] = self.vertex_interp(grid.p[0],grid.p[1],grid.val[0],grid.val[1]);
         if (edgeTable[cubeIndex] & 2):
             vertlist[1] = self.vertex_interp(grid.p[1],grid.p[2],grid.val[1],grid.val[2]);
         if (edgeTable[cubeIndex] & 4):
             vertlist[2] = self.vertex_interp(grid.p[2],grid.p[3],grid.val[2],grid.val[3]);
         if (edgeTable[cubeIndex] & 8):
             vertlist[3] = self.vertex_interp(grid.p[3],grid.p[0],grid.val[3],grid.val[0]);
         if (edgeTable[cubeIndex] & 16):
             vertlist[4] = self.vertex_interp(grid.p[4],grid.p[5],grid.val[4],grid.val[5]);
         if (edgeTable[cubeIndex] & 32):
             vertlist[5] = self.vertex_interp(grid.p[5],grid.p[6],grid.val[5],grid.val[6]);
         if (edgeTable[cubeIndex] & 64):
             vertlist[6] = self.vertex_interp(grid.p[6],grid.p[7],grid.val[6],grid.val[7]);
         if (edgeTable[cubeIndex] & 128):
             vertlist[7] = self.vertex_interp(grid.p[7],grid.p[4],grid.val[7],grid.val[4]);
         if (edgeTable[cubeIndex] & 256):
             vertlist[8] = self.vertex_interp(grid.p[0],grid.p[4],grid.val[0],grid.val[4]);
         if (edgeTable[cubeIndex] & 512):
             vertlist[9] = self.vertex_interp(grid.p[1],grid.p[5],grid.val[1],grid.val[5]);
         if (edgeTable[cubeIndex] & 1024):
             vertlist[10] = self.vertex_interp(grid.p[2],grid.p[6],grid.val[2],grid.val[6]);
         if (edgeTable[cubeIndex] & 2048):
             vertlist[11] = self.vertex_interp(grid.p[3],grid.p[7],grid.val[3],grid.val[7]);
         //根据交点坐标确定三角形面片,并进行保存
         for (int i=0; triTable[cubeIndex][i] != -1; i+=3):
         tri[numOftriangle].p[0] = vertlist[ triTable[cubeIndex][i  ] ];
         tri[numOftriangle].p[1] = vertlist[ triTable[cubeIndex][i+1] ];
         tri[numOftriangle].p[2] = vertlist[ triTable[cubeIndex][i+2] ];
         numOftriangle++;
Exemple #16
0
    def build_short_circuit_or(operands):
        if len(operands) == 1:
            return operands[0].ptr

        val = ti.expr_init(None)
        lhs = operands[0].ptr
        ti.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
Exemple #17
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 = ti.expr_init(value)
            ctx.create_variable(target.id, var)
        else:
            var = target.ptr
            var.assign(value)
        return var
Exemple #18
0
 def atomic_add(self, other):
   import taichi as ti
   other_ptr = ti.wrap_scalar(other).ptr
   return ti.expr_init(taichi_lang_core.expr_atomic_add(self.ptr, other_ptr))
Exemple #19
0
def shuffle(a, *ks):
    ret = []
    for k in ks:
        t = a.subscript(k)
        ret.append(ti.expr_init(t))
    return ti.Vector(ret)
Exemple #20
0
 def all(self):
     import taichi as ti
     ret = self.entries[0] != ti.expr_init(0)
     for i in range(1, len(self.entries)):
         ret = ret + (self.entries[i] != ti.expr_init(0))
     return -(ret == ti.expr_init(-len(self.entries)))
Exemple #21
0
def append(l, indices, val):
    import taichi as ti
    a = ti.expr_init(
        ti_core.insert_append(l.snode.ptr, make_expr_group(indices),
                              Expr(val).ptr))
    return a
Exemple #22
0
 def variable(self):
     return self.__class__(*(ti.expr_init(e) for e in self.entries))
Exemple #23
0
 def __init__(self):
     self.p = [ti.expr_init(ti.Vector.zero(int, 3)) for t in range(8)]
     self.val = [ti.expr_init(0.0) for t in range(8)]
Exemple #24
0
 def assign(self, value):
     self.parent[self.name] = ti.expr_init(value)
Exemple #25
0
 def __isub__(self, other):
   # TODO: add atomic_sub()
   import taichi as ti
   ti.expr_init(taichi_lang_core.expr_atomic_sub(self.ptr, other.ptr))
Exemple #26
0
 def __init__(self, **kwargs):
     res = dict()
     for k, v in kwargs.items():
         res[k] = ti.expr_init(v)
     super().__init__(res)