From ff614b99d82425de6abc8172aa53d5d8244b4ab3 Mon Sep 17 00:00:00 2001 From: xumingkuan Date: Tue, 25 Feb 2020 18:21:24 -0500 Subject: [PATCH 01/12] tmp --- tests/python/test_compare.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 tests/python/test_compare.py diff --git a/tests/python/test_compare.py b/tests/python/test_compare.py new file mode 100644 index 0000000000000..2122bc5694a80 --- /dev/null +++ b/tests/python/test_compare.py @@ -0,0 +1,17 @@ +import taichi as ti + + +@ti.all_archs +def test_compare(): + a = ti.var(ti.i32) + ti.root.dynamic(ti.i, 256).place(a) + + @ti.kernel + def func(): + # t = 0 <= ti.append(a.parent(), [], 1) < 2 + t = 1 < 0 + print(t) + # t = ti.chain_compare([0, 1], [2]) + + func() + assert a[1] == 0 \ No newline at end of file From dee4883c83c3b64a0d84a1f4a4490e0ac93423b2 Mon Sep 17 00:00:00 2001 From: xumingkuan Date: Wed, 26 Feb 2020 14:46:56 -0500 Subject: [PATCH 02/12] Avoid duplicate evaluations in chaining comparison --- python/taichi/lang/impl.py | 29 ++++++++++++++++++++ python/taichi/lang/transformer.py | 45 ++++++++++++++++++++++--------- tests/python/test_compare.py | 24 +++++++++++++---- 3 files changed, 80 insertions(+), 18 deletions(-) diff --git a/python/taichi/lang/impl.py b/python/taichi/lang/impl.py index 4363aa5d31497..71ce869fd34f4 100644 --- a/python/taichi/lang/impl.py +++ b/python/taichi/lang/impl.py @@ -36,6 +36,7 @@ def wrap_scalar(x): def atomic_add(a, b): return a.atomic_add(b) + def subscript(value, *indices): import numpy as np if isinstance(value, np.ndarray): @@ -66,6 +67,34 @@ def subscript(value, *indices): return Expr(taichi_lang_core.subscript(value.ptr, indices_expr_group)) +def chain_compare(comparators, ops): + assert len(comparators) == len(ops) + 1, \ + f'Chain comparison invoked with {len(comparators)} comparators but {len(ops)} operators' + evaluated_comparators = [] + for i in range(len(comparators)): + evaluated_comparators += [expr_init(comparators[i])] + ret = expr_init(True) + for i in range(len(ops)): + lhs = evaluated_comparators[i] + rhs = evaluated_comparators[i + 1] + if ops[i] == 'Lt': + now = lhs < rhs + elif ops[i] == 'LtE': + now = lhs <= rhs + elif ops[i] == 'Gt': + now = lhs > rhs + elif ops[i] == 'GtE': + now = lhs >= rhs + elif ops[i] == 'Eq': + now = lhs == rhs + elif ops[i] == 'NotEq': + now = lhs != rhs + else: + assert False, f'Unknown operator {ops[i]}' + ret = ret.logical_and(now) + return ret + + class PyTaichi: def __init__(self, kernels=[]): diff --git a/python/taichi/lang/transformer.py b/python/taichi/lang/transformer.py index 0f34a1a1c7ecc..9ae412e060ba4 100644 --- a/python/taichi/lang/transformer.py +++ b/python/taichi/lang/transformer.py @@ -524,21 +524,40 @@ def visit_UnaryOp(self, node): def visit_Compare(self, node): self.generic_visit(node) - ret = None comparators = [node.left] + node.comparators - for i in range(len(node.comparators)): - new_cmp = ast.Compare(left=comparators[i], ops=[node.ops[i]], comparators=[comparators[i + 1]]) - ast.copy_location(new_cmp, node) - if ret is None: - ret = new_cmp + ops = [] + for i in range(len(node.ops)): + if isinstance(node.ops[i], ast.Lt): + op_str = 'Lt' + elif isinstance(node.ops[i], ast.LtE): + op_str = 'LtE' + elif isinstance(node.ops[i], ast.Gt): + op_str = 'Gt' + elif isinstance(node.ops[i], ast.GtE): + op_str = 'GtE' + elif isinstance(node.ops[i], ast.Eq): + op_str = 'Eq' + elif isinstance(node.ops[i], ast.NotEq): + op_str = 'NotEq' + elif isinstance(node.ops[i], ast.In): + raise TaichiSyntaxError('"in" is not supported in Taichi kernels.') + elif isinstance(node.ops[i], ast.NotIn): + raise TaichiSyntaxError('"not in" is not supported in Taichi kernels.') + elif isinstance(node.ops[i], ast.Is): + raise TaichiSyntaxError('"is" is not supported in Taichi kernels.') + elif isinstance(node.ops[i], ast.IsNot): + raise TaichiSyntaxError('"is not" is not supported in Taichi kernels.') else: - ret = ast.BoolOp(op=ast.And(), values=[ret, new_cmp]) - ret = self.visit_BoolOp(ret) - ast.copy_location(ret, node) - - self.generic_visit(ret) - return ret - + raise Exception(f'Unknown operator {node.ops[i]}') + ops += [ast.copy_location(ast.Str(s=op_str), node)] + + call = ast.Call( + func=self.parse_expr('ti.chain_compare'), + args=[ast.copy_location(ast.List(elts=comparators, ctx=ast.Load()), node), + ast.copy_location(ast.List(elts=ops, ctx=ast.Load()), node)], + keywords=[]) + call = ast.copy_location(call, node) + return call def visit_BoolOp(self, node): self.generic_visit(node) diff --git a/tests/python/test_compare.py b/tests/python/test_compare.py index 2122bc5694a80..fbe2f7a738886 100644 --- a/tests/python/test_compare.py +++ b/tests/python/test_compare.py @@ -5,13 +5,27 @@ def test_compare(): a = ti.var(ti.i32) ti.root.dynamic(ti.i, 256).place(a) + b = ti.var(ti.i32, shape=()) + c = ti.var(ti.i32, shape=()) + d = ti.var(ti.i32, shape=()) @ti.kernel def func(): - # t = 0 <= ti.append(a.parent(), [], 1) < 2 - t = 1 < 0 - print(t) - # t = ti.chain_compare([0, 1], [2]) + a[2] = 0 <= ti.append(a.parent(), [], 10) < 1 + b[None] = 2 + c[None] = 3 + d[None] = 3 + a[3] = b < c == d + a[4] = b <= c != d + a[5] = c > b < d + a[6] = c == d != b < d > b >= b <= c + # a[10] = b is not c # not supported func() - assert a[1] == 0 \ No newline at end of file + assert a[0] == 10 + assert a[1] == 0 # not appended twice + assert a[2] + assert a[3] + assert not a[4] + assert a[5] + assert a[6] \ No newline at end of file From 6370968fb1e67215ff1885a5f4363d0f1b280593 Mon Sep 17 00:00:00 2001 From: xumingkuan Date: Wed, 26 Feb 2020 14:50:35 -0500 Subject: [PATCH 03/12] minor: new line --- tests/python/test_compare.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/python/test_compare.py b/tests/python/test_compare.py index fbe2f7a738886..25ff364d44bb0 100644 --- a/tests/python/test_compare.py +++ b/tests/python/test_compare.py @@ -28,4 +28,4 @@ def func(): assert a[3] assert not a[4] assert a[5] - assert a[6] \ No newline at end of file + assert a[6] From c3996e79fbbe662813e53ea1266dcd9e936e7cf8 Mon Sep 17 00:00:00 2001 From: Yuanming Hu Date: Tue, 25 Feb 2020 15:56:14 -0500 Subject: [PATCH 04/12] removed taichi/lang.h and taichi/llvm_jit.h --- taichi/lang.h | 2 -- taichi/llvm_jit.h | 2 -- taichi/transforms/make_adjoint.cpp | 2 +- taichi/transforms/type_check.cpp | 2 +- tests/cpp/test_alg_simp.cpp | 2 +- tests/cpp/test_simplify.cpp | 2 +- 6 files changed, 4 insertions(+), 8 deletions(-) delete mode 100644 taichi/lang.h delete mode 100644 taichi/llvm_jit.h diff --git a/taichi/lang.h b/taichi/lang.h deleted file mode 100644 index 4119fc3b44a7e..0000000000000 --- a/taichi/lang.h +++ /dev/null @@ -1,2 +0,0 @@ -#pragma once -#include "tlang.h" \ No newline at end of file diff --git a/taichi/llvm_jit.h b/taichi/llvm_jit.h deleted file mode 100644 index 139597f9cb07c..0000000000000 --- a/taichi/llvm_jit.h +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/taichi/transforms/make_adjoint.cpp b/taichi/transforms/make_adjoint.cpp index b5431f6828d35..7ccc698850156 100644 --- a/taichi/transforms/make_adjoint.cpp +++ b/taichi/transforms/make_adjoint.cpp @@ -1,6 +1,6 @@ #include #include "../ir.h" -#include +#include TLANG_NAMESPACE_BEGIN diff --git a/taichi/transforms/type_check.cpp b/taichi/transforms/type_check.cpp index 57c5cc566ba69..7cfa5e312b634 100644 --- a/taichi/transforms/type_check.cpp +++ b/taichi/transforms/type_check.cpp @@ -1,7 +1,7 @@ // Type checking #include "../ir.h" -#include +#include TLANG_NAMESPACE_BEGIN diff --git a/tests/cpp/test_alg_simp.cpp b/tests/cpp/test_alg_simp.cpp index a56f0b1642ef8..79e6254e04851 100644 --- a/tests/cpp/test_alg_simp.cpp +++ b/tests/cpp/test_alg_simp.cpp @@ -1,4 +1,4 @@ -#include +#include #include TLANG_NAMESPACE_BEGIN diff --git a/tests/cpp/test_simplify.cpp b/tests/cpp/test_simplify.cpp index df087f0bc3732..40e4e96305353 100644 --- a/tests/cpp/test_simplify.cpp +++ b/tests/cpp/test_simplify.cpp @@ -1,4 +1,4 @@ -#include +#include #include TLANG_NAMESPACE_BEGIN From 41f3ffa8e00013fb6d63ab1fad502af8e388fa74 Mon Sep 17 00:00:00 2001 From: xumingkuan Date: Tue, 25 Feb 2020 18:21:24 -0500 Subject: [PATCH 05/12] tmp --- tests/python/test_compare.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 tests/python/test_compare.py diff --git a/tests/python/test_compare.py b/tests/python/test_compare.py new file mode 100644 index 0000000000000..2122bc5694a80 --- /dev/null +++ b/tests/python/test_compare.py @@ -0,0 +1,17 @@ +import taichi as ti + + +@ti.all_archs +def test_compare(): + a = ti.var(ti.i32) + ti.root.dynamic(ti.i, 256).place(a) + + @ti.kernel + def func(): + # t = 0 <= ti.append(a.parent(), [], 1) < 2 + t = 1 < 0 + print(t) + # t = ti.chain_compare([0, 1], [2]) + + func() + assert a[1] == 0 \ No newline at end of file From da6ef2072946d22c4a5b7f0c863b7ab7011b7164 Mon Sep 17 00:00:00 2001 From: Ye Kuang Date: Wed, 26 Feb 2020 10:18:12 +0900 Subject: [PATCH 06/12] Make sure KernelTemplateMapper extractors's size is the same as the number of args (#534) * Make sure KernelTemplateMapper extractors's size is the same as the number of args Fixes #531 * fix test --- python/taichi/lang/kernel.py | 5 ++++- tests/python/test_empty.py | 10 ++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/python/taichi/lang/kernel.py b/python/taichi/lang/kernel.py index 2f0e89d415add..4d2c8671cce7e 100644 --- a/python/taichi/lang/kernel.py +++ b/python/taichi/lang/kernel.py @@ -60,7 +60,10 @@ class KernelTemplateMapper: def __init__(self, annotations, template_slot_locations): self.annotations = annotations - self.extractors = tuple((i, anno.extract) for (i, anno) in enumerate(self.annotations) if hasattr(anno, 'extract')) + # Make sure extractors's size is the same as the number of args + dummy_extract = lambda arg: (type(arg).__name__, ) + self.extractors = tuple((i, getattr(anno, 'extract', dummy_extract)) + for (i, anno) in enumerate(self.annotations)) self.num_args = len(annotations) self.template_slot_locations = template_slot_locations self.mapping = {} diff --git a/tests/python/test_empty.py b/tests/python/test_empty.py index c85e7c1b81fd6..d2d8372cc120e 100644 --- a/tests/python/test_empty.py +++ b/tests/python/test_empty.py @@ -8,3 +8,13 @@ def func(): pass func() + +@ti.all_archs +def test_empty_args(): + + @ti.kernel + def func(x: ti.i32, arr: ti.ext_arr()): + pass + + import numpy as np + func(42, np.arange(10, dtype=np.float32)) From 65a8db11879b232c73ace92fc32fa48fe353c23d Mon Sep 17 00:00:00 2001 From: Yuanming Hu Date: Tue, 25 Feb 2020 20:54:39 -0500 Subject: [PATCH 07/12] Update README.md --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index cad11d610a306..46b3623781abe 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,14 @@ python3 -m pip install taichi-nightly-cuda-10-1 |**PyPI**|[![Build Status](https://travis-ci.com/yuanming-hu/taichi-wheels-test.svg?branch=master)](https://travis-ci.com/yuanming-hu/taichi-wheels-test)|[![Build Status](https://travis-ci.com/yuanming-hu/taichi-wheels-test.svg?branch=master)](https://travis-ci.com/yuanming-hu/taichi-wheels-test)|[![Build status](https://ci.appveyor.com/api/projects/status/39ar9wa8yd49je7o?svg=true)](https://ci.appveyor.com/project/IteratorAdvance/taichi-wheels-test)| ## Updates +- (Feb 25, 2020) v0.5.3 released + - Better error message when try to declare tensors after kernel invocation (by **Yubin Peng [archibate]**) + - Logging: `ti.warning` renamed to `ti.warn` + - Arch: `ti.x86_64` renamed to `ti.x64`. `ti.x86_64` is deprecated and will be removed in a future release + - (For developers) Improved runtime bit code compilation thread safety (by **Yubin Peng [archibate]**) + - Improved OS X GUI performance (by **Ye Kuang [k-ye]**) + - Experimental support for new integer types `u8, i8, u16, i16, u32` (by **Yubin Peng [archibate]**) + - Update doc (by **Ye Kuang [k-ye]**) - (Feb 20, 2020) v0.5.2 released - Gradients for `ti.pow` now supported (by **Yubin Peng [archibate]**) - Multi-threaded unit testing (by **Yubin Peng [archibate]**) @@ -45,6 +53,7 @@ python3 -m pip install taichi-nightly-cuda-10-1 - Use environment variable `TI_TEST_THREADS` to override testing threads - [For Taichi developers, bug fix] `ti.init(print_processed=True)` renamed to `ti.init(print_preprocessed=True)` - Various development infrastructure improvements by **Yubin Peng [archibate]** + - Official Python3.6 - Python3.8 packages on OS X (by **wYw [Detavern]**) - (Feb 16, 2020) v0.5.1 released - Keyboard and mouse events supported in the GUI system. Check out [mpm128.py](https://github.com/taichi-dev/taichi/blob/4f5cc09ae0e35a47ad71fdc582c1ecd5202114d8/examples/mpm128.py) for a interactive demo! (by **Yubin Peng [archibate] and Ye Kuang [k-ye]**) - Basic algebraic simplification passes (by **Mingkuan Xu [xumingkuan]**) From bf384342056b9d62aba18f74ceb1c442cf9c4f41 Mon Sep 17 00:00:00 2001 From: xumingkuan Date: Wed, 26 Feb 2020 14:46:56 -0500 Subject: [PATCH 08/12] Avoid duplicate evaluations in chaining comparison --- python/taichi/lang/impl.py | 29 ++++++++++++++++++++ python/taichi/lang/transformer.py | 45 ++++++++++++++++++++++--------- tests/python/test_compare.py | 24 +++++++++++++---- 3 files changed, 80 insertions(+), 18 deletions(-) diff --git a/python/taichi/lang/impl.py b/python/taichi/lang/impl.py index 4363aa5d31497..71ce869fd34f4 100644 --- a/python/taichi/lang/impl.py +++ b/python/taichi/lang/impl.py @@ -36,6 +36,7 @@ def wrap_scalar(x): def atomic_add(a, b): return a.atomic_add(b) + def subscript(value, *indices): import numpy as np if isinstance(value, np.ndarray): @@ -66,6 +67,34 @@ def subscript(value, *indices): return Expr(taichi_lang_core.subscript(value.ptr, indices_expr_group)) +def chain_compare(comparators, ops): + assert len(comparators) == len(ops) + 1, \ + f'Chain comparison invoked with {len(comparators)} comparators but {len(ops)} operators' + evaluated_comparators = [] + for i in range(len(comparators)): + evaluated_comparators += [expr_init(comparators[i])] + ret = expr_init(True) + for i in range(len(ops)): + lhs = evaluated_comparators[i] + rhs = evaluated_comparators[i + 1] + if ops[i] == 'Lt': + now = lhs < rhs + elif ops[i] == 'LtE': + now = lhs <= rhs + elif ops[i] == 'Gt': + now = lhs > rhs + elif ops[i] == 'GtE': + now = lhs >= rhs + elif ops[i] == 'Eq': + now = lhs == rhs + elif ops[i] == 'NotEq': + now = lhs != rhs + else: + assert False, f'Unknown operator {ops[i]}' + ret = ret.logical_and(now) + return ret + + class PyTaichi: def __init__(self, kernels=[]): diff --git a/python/taichi/lang/transformer.py b/python/taichi/lang/transformer.py index 0f34a1a1c7ecc..9ae412e060ba4 100644 --- a/python/taichi/lang/transformer.py +++ b/python/taichi/lang/transformer.py @@ -524,21 +524,40 @@ def visit_UnaryOp(self, node): def visit_Compare(self, node): self.generic_visit(node) - ret = None comparators = [node.left] + node.comparators - for i in range(len(node.comparators)): - new_cmp = ast.Compare(left=comparators[i], ops=[node.ops[i]], comparators=[comparators[i + 1]]) - ast.copy_location(new_cmp, node) - if ret is None: - ret = new_cmp + ops = [] + for i in range(len(node.ops)): + if isinstance(node.ops[i], ast.Lt): + op_str = 'Lt' + elif isinstance(node.ops[i], ast.LtE): + op_str = 'LtE' + elif isinstance(node.ops[i], ast.Gt): + op_str = 'Gt' + elif isinstance(node.ops[i], ast.GtE): + op_str = 'GtE' + elif isinstance(node.ops[i], ast.Eq): + op_str = 'Eq' + elif isinstance(node.ops[i], ast.NotEq): + op_str = 'NotEq' + elif isinstance(node.ops[i], ast.In): + raise TaichiSyntaxError('"in" is not supported in Taichi kernels.') + elif isinstance(node.ops[i], ast.NotIn): + raise TaichiSyntaxError('"not in" is not supported in Taichi kernels.') + elif isinstance(node.ops[i], ast.Is): + raise TaichiSyntaxError('"is" is not supported in Taichi kernels.') + elif isinstance(node.ops[i], ast.IsNot): + raise TaichiSyntaxError('"is not" is not supported in Taichi kernels.') else: - ret = ast.BoolOp(op=ast.And(), values=[ret, new_cmp]) - ret = self.visit_BoolOp(ret) - ast.copy_location(ret, node) - - self.generic_visit(ret) - return ret - + raise Exception(f'Unknown operator {node.ops[i]}') + ops += [ast.copy_location(ast.Str(s=op_str), node)] + + call = ast.Call( + func=self.parse_expr('ti.chain_compare'), + args=[ast.copy_location(ast.List(elts=comparators, ctx=ast.Load()), node), + ast.copy_location(ast.List(elts=ops, ctx=ast.Load()), node)], + keywords=[]) + call = ast.copy_location(call, node) + return call def visit_BoolOp(self, node): self.generic_visit(node) diff --git a/tests/python/test_compare.py b/tests/python/test_compare.py index 2122bc5694a80..fbe2f7a738886 100644 --- a/tests/python/test_compare.py +++ b/tests/python/test_compare.py @@ -5,13 +5,27 @@ def test_compare(): a = ti.var(ti.i32) ti.root.dynamic(ti.i, 256).place(a) + b = ti.var(ti.i32, shape=()) + c = ti.var(ti.i32, shape=()) + d = ti.var(ti.i32, shape=()) @ti.kernel def func(): - # t = 0 <= ti.append(a.parent(), [], 1) < 2 - t = 1 < 0 - print(t) - # t = ti.chain_compare([0, 1], [2]) + a[2] = 0 <= ti.append(a.parent(), [], 10) < 1 + b[None] = 2 + c[None] = 3 + d[None] = 3 + a[3] = b < c == d + a[4] = b <= c != d + a[5] = c > b < d + a[6] = c == d != b < d > b >= b <= c + # a[10] = b is not c # not supported func() - assert a[1] == 0 \ No newline at end of file + assert a[0] == 10 + assert a[1] == 0 # not appended twice + assert a[2] + assert a[3] + assert not a[4] + assert a[5] + assert a[6] \ No newline at end of file From 14240ee7e8d4b02e4e440ea9de5e85beacc4c1e5 Mon Sep 17 00:00:00 2001 From: xumingkuan Date: Wed, 26 Feb 2020 14:50:35 -0500 Subject: [PATCH 09/12] minor: new line --- tests/python/test_compare.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/python/test_compare.py b/tests/python/test_compare.py index fbe2f7a738886..25ff364d44bb0 100644 --- a/tests/python/test_compare.py +++ b/tests/python/test_compare.py @@ -28,4 +28,4 @@ def func(): assert a[3] assert not a[4] assert a[5] - assert a[6] \ No newline at end of file + assert a[6] From 069f596febe93cedaad19107fe5da3ad48566066 Mon Sep 17 00:00:00 2001 From: xumingkuan Date: Wed, 26 Feb 2020 15:36:02 -0500 Subject: [PATCH 10/12] improve tests --- tests/python/test_compare.py | 113 ++++++++++++++++++++++++++++++----- 1 file changed, 99 insertions(+), 14 deletions(-) diff --git a/tests/python/test_compare.py b/tests/python/test_compare.py index 25ff364d44bb0..b2be8a35e89b7 100644 --- a/tests/python/test_compare.py +++ b/tests/python/test_compare.py @@ -2,30 +2,115 @@ @ti.all_archs -def test_compare(): +def test_compare_basics(): + a = ti.var(ti.i32) + ti.root.dynamic(ti.i, 256).place(a) + b = ti.var(ti.i32, shape=()) + c = ti.var(ti.i32, shape=()) + + @ti.kernel + def func(): + b[None] = 3 + c[None] = 5 + a[0] = b < c + a[1] = b <= c + a[2] = b > c + a[3] = b >= c + a[4] = b == c + a[5] = b != c + a[6] = c < b + a[7] = c <= b + a[8] = c > b + a[9] = c >= b + a[10] = c == b + a[11] = c != b + # a[12] = b is not c # not supported + + func() + assert a[0] + assert a[1] + assert not a[2] + assert not a[3] + assert not a[4] + assert a[5] + assert not a[6] + assert not a[7] + assert a[8] + assert a[9] + assert not a[10] + assert a[11] + + +@ti.all_archs +def test_compare_equality(): a = ti.var(ti.i32) ti.root.dynamic(ti.i, 256).place(a) b = ti.var(ti.i32, shape=()) c = ti.var(ti.i32, shape=()) - d = ti.var(ti.i32, shape=()) + + @ti.kernel + def func(): + b[None] = 3 + c[None] = 3 + a[0] = b < c + a[1] = b <= c + a[2] = b > c + a[3] = b >= c + a[4] = b == c + a[5] = b != c + a[6] = c < b + a[7] = c <= b + a[8] = c > b + a[9] = c >= b + a[10] = c == b + a[11] = c != b + + func() + assert not a[0] + assert a[1] + assert not a[2] + assert a[3] + assert a[4] + assert not a[5] + assert not a[6] + assert a[7] + assert not a[8] + assert a[9] + assert a[10] + assert not a[11] + + +@ti.all_archs +def test_no_duplicate_eval(): + a = ti.var(ti.i32) + ti.root.dynamic(ti.i, 256).place(a) @ti.kernel def func(): a[2] = 0 <= ti.append(a.parent(), [], 10) < 1 + + func() + assert a[0] == 10 + assert a[1] == 0 # not appended twice + assert a[2] # ti.append returns 0 + + +@ti.all_archs +def test_chain_compare(): + a = ti.var(ti.i32) + ti.root.dynamic(ti.i, 256).place(a) + b = ti.var(ti.i32, shape=()) + c = ti.var(ti.i32, shape=()) + d = ti.var(ti.i32, shape=()) + + @ti.kernel + def func(): b[None] = 2 c[None] = 3 d[None] = 3 - a[3] = b < c == d - a[4] = b <= c != d - a[5] = c > b < d - a[6] = c == d != b < d > b >= b <= c - # a[10] = b is not c # not supported + a[0] = c == d != b < d > b >= b <= c + a[1] = b <= c != d > b == b func() - assert a[0] == 10 - assert a[1] == 0 # not appended twice - assert a[2] - assert a[3] - assert not a[4] - assert a[5] - assert a[6] + assert a[0] + assert not a[1] From c06d850a44e3d34875ed5a4142a6f9d2edf64f73 Mon Sep 17 00:00:00 2001 From: xumingkuan Date: Wed, 26 Feb 2020 16:51:38 -0500 Subject: [PATCH 11/12] Do not apply the generic visitor if the function called is ti.static --- python/taichi/lang/transformer.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/python/taichi/lang/transformer.py b/python/taichi/lang/transformer.py index 9ae412e060ba4..10832a8763678 100644 --- a/python/taichi/lang/transformer.py +++ b/python/taichi/lang/transformer.py @@ -427,7 +427,12 @@ def visit_Continue(self, node): ) def visit_Call(self, node): - self.generic_visit(node) + if not (isinstance(node.func, ast.Attribute) + and isinstance(node.func.value, ast.Name) + and node.func.value.id == 'ti' + and node.func.attr == 'static'): + # Do not apply the generic visitor if the function called is ti.static + self.generic_visit(node) if isinstance(node.func, ast.Name): func_name = node.func.id if func_name == 'print': From a07e2bb1cfd4813b09d46dbf6de4a0b472b8238b Mon Sep 17 00:00:00 2001 From: xumingkuan Date: Wed, 26 Feb 2020 17:28:37 -0500 Subject: [PATCH 12/12] Disallow Expr.__getitem__ in Taichi-scope --- python/taichi/lang/expr.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/python/taichi/lang/expr.py b/python/taichi/lang/expr.py index 2a9680be40ad4..07e58aa530cce 100644 --- a/python/taichi/lang/expr.py +++ b/python/taichi/lang/expr.py @@ -199,6 +199,8 @@ def __setitem__(self, key, value): self.setter(value, *key) def __getitem__(self, key): + import taichi as ti + assert not ti.get_runtime().inside_kernel if not Expr.layout_materialized: self.materialize_layout_callback() self.initialize_accessor()