From 9c1a388f116959f30b8be437cd39c9c80b7b1c17 Mon Sep 17 00:00:00 2001 From: jim19930609 Date: Thu, 28 Apr 2022 15:11:10 +0800 Subject: [PATCH 1/2] [doc] Updated documentations for type promotion rules --- docs/lang/articles/basic/type.md | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/docs/lang/articles/basic/type.md b/docs/lang/articles/basic/type.md index a245b22690ebf..1171c407338ef 100644 --- a/docs/lang/articles/basic/type.md +++ b/docs/lang/articles/basic/type.md @@ -100,11 +100,31 @@ As a rule of thumb, implicit type casting is a major source of bugs. And Taichi #### Implicit type casting in binary operations -Taichi follows the [implicit conversion rules](https://en.cppreference.com/w/c/language/conversion) for the C programming language and implicitly casts operands in a [binary operation](https://en.wikipedia.org/wiki/Binary_operation) into a *common type* if the operation involves different data types. Following are two most straightforward rules for determining the common type in a binary operation: +Taichi mostly follows the [implicit conversion rules](https://en.cppreference.com/w/c/language/conversion) for the C programming language and implicitly casts operands in a [binary operation](https://en.wikipedia.org/wiki/Binary_operation) into a *common type* if the operation involves different data types. Following are two most straightforward rules for determining the common type in a binary operation: - `i32 + f32 = f32` (`int` + `float` = `float`) - `i32 + i64 = i64` (low precision bits + high precision bits = high precision bits) +Note that in C++: `i8 + i8 = i32`, which makes no sense to Taichi use cases. Therefore we implemented our own rules for this kind of operations: +``` +i8 + i8 = i8 +i8 + i16 = i16 +i8 + u8 = u8 +i8 + u16 = u16 +i16 + i8 = i16 +i16 + i16 = i16 +i16 + u8 = i16 +i16 + u16 = u16 +u8 + i8 = u8 +u8 + i16 = i16 +u8 + u8 = u8 +u8 + u16 = u16 +u16 + i8 = u16 +u16 + i16 = u16 +u16 + u8 = u16 +u16 + u16 = u16 +``` + #### Implicit type casting in assignments When you assign a value to a variable of a different data type, Taichi implicitly casts the value into that type. Further, if the type of the variable is *not* the common type, a warning of precision loss occurs. From 3f01e25c85f07c79111f7733ebfd00c5a58af5ed Mon Sep 17 00:00:00 2001 From: jim19930609 Date: Fri, 29 Apr 2022 14:31:49 +0800 Subject: [PATCH 2/2] Rearranged type promotion docs --- docs/lang/articles/basic/type.md | 47 +++++++++++++++++--------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/docs/lang/articles/basic/type.md b/docs/lang/articles/basic/type.md index 1171c407338ef..1e2fd7511ced5 100644 --- a/docs/lang/articles/basic/type.md +++ b/docs/lang/articles/basic/type.md @@ -100,30 +100,33 @@ As a rule of thumb, implicit type casting is a major source of bugs. And Taichi #### Implicit type casting in binary operations -Taichi mostly follows the [implicit conversion rules](https://en.cppreference.com/w/c/language/conversion) for the C programming language and implicitly casts operands in a [binary operation](https://en.wikipedia.org/wiki/Binary_operation) into a *common type* if the operation involves different data types. Following are two most straightforward rules for determining the common type in a binary operation: +Taichi implements its own implicit type casting rules for binary operations, which are slightly different from [those for the C programming language](https://en.cppreference.com/w/c/language/conversion). -- `i32 + f32 = f32` (`int` + `float` = `float`) -- `i32 + i64 = i64` (low precision bits + high precision bits = high precision bits) +In general we have three rules with descending priority: -Note that in C++: `i8 + i8 = i32`, which makes no sense to Taichi use cases. Therefore we implemented our own rules for this kind of operations: -``` -i8 + i8 = i8 -i8 + i16 = i16 -i8 + u8 = u8 -i8 + u16 = u16 -i16 + i8 = i16 -i16 + i16 = i16 -i16 + u8 = i16 -i16 + u16 = u16 -u8 + i8 = u8 -u8 + i16 = i16 -u8 + u8 = u8 -u8 + u16 = u16 -u16 + i8 = u16 -u16 + i16 = u16 -u16 + u8 = u16 -u16 + u16 = u16 -``` +1. integral OP floating_point -> floating_point +- `i32 + f32 -> f32` +- `i16 + f16 -> f16` + +2. low_precision_bits OP high_precision_bits -> high_precision_bits +- `i16 + i32 -> i32` +- `u8 + u16 -> u16` + +3. signed OP unsigned -> unsigned +- `u32 + i32 -> u32` +- `u8 + i8 -> u8` + +For conflicting rules, only the highest priority one will be applied. +- `u8 + i16 -> i16` (rule #2 conflicts with rule #3: apply rule #2) +- `f16 + i32 -> f16` (rule #1 conflicts with rule #2: apply rule #1) + +A few exceptions: +1. bit-shift operations: always follow lhs's dtype +- `u8 << i32 -> u8` +- `i16 << i8 -> i16` + +2. logical operations: always return i32 +3. comparison operations: always return i32 #### Implicit type casting in assignments