类型系统

Taichi supports common numerical data types. Each type is denoted as a character indicating its category and a number of precision bits, e.g., i32 and f64.

The category can be one of:

  • i for signed integers, e.g. 233, -666
  • u for unsigned integers, e.g. 233, 666
  • f for floating point numbers, e.g. 2.33, 1e-4

The digital number can be one of:

  • 8
  • 16
  • 32
  • 64

It represents how many bits are used in storing the data. The larger the bit number, the higher the precision is.

For example, the two most commonly used types:

  • i32 represents a 32-bit signed integer.
  • f32 represents a 32-bit floating pointer number.

支持的类型

目前,Taichi支持的基本类型有

  • int8 ti.i8
  • int16 ti.i16
  • int32 ti.i32
  • int64 ti.i64
  • uint8 ti.u8
  • uint16 ti.u16
  • uint32 ti.u32
  • uint64 ti.u64
  • float32 ti.f32
  • float64 ti.f64

注解

每种后端支持的类型分别有:

类型 CPU/CUDA OpenGL Metal
i8 OK N/A OK
i16 OK N/A OK
i32 OK OK OK
i64 OK EXT N/A
u8 OK N/A OK
u16 OK N/A OK
u32 OK N/A OK
u64 OK N/A N/A
f32 OK OK OK
f64 OK OK N/A

(OK:已支持,EXT:需要扩展支持,N/A:目前不支持)

注解

Boolean types are represented using ti.i32.

Type promotion

Binary operations on different types will give you a promoted type, following the C programming language convention, e.g.:

  • i32 + f32 = f32 (integer + float = float)
  • i32 + i64 = i64 (less-bits + more-bits = more-bits)

Basically it will try to choose the more precise type to contain the result value.

默认精度

By default, all numerical literals have 32-bit precisions. For example, 42 has type ti.i32 and 3.14 has type ti.f32.

Default integer and float-point precisions (default_ip and default_fp) can be specified when initializing Taichi:

ti.init(default_fp=ti.f32)
ti.init(default_fp=ti.f64)

ti.init(default_ip=ti.i32)
ti.init(default_ip=ti.i64)

Also note that you may use float or int in type definitions as aliases for default precisions, e.g.:

ti.init(default_ip=ti.i64, default_fp=ti.f32)

x = ti.var(float, 5)
y = ti.var(int, 5)
# is equivalent to:
x = ti.var(ti.f32, 5)
y = ti.var(ti.i64, 5)

def func(a: float) -> int:
    ...

# is equivalent to:
def func(a: ti.f32) -> ti.i64:
    ...

类型转换

Implicit casts

警告

The type of a variable is determinated on it’s initialization.

When a low-precision variable is assigned to a high-precision variable, it will be implicitly promoted to the wide type and no warning will be raised:

a = 1.7
a = 1
print(a)  # 1.0

When a high-precision variable is assigned to a low-precision type, it will be implicitly down-cast into the low-precision type and Taichi will raise a warning:

a = 1
a = 1.7
print(a)  # 1

Explicit casts

You may use ti.cast to explicitly cast scalar values between different types:

a = 1.7
b = ti.cast(a, ti.i32)  # 1
c = ti.cast(b, ti.f32)  # 1.0

Equivalently, use int() and float() to convert values to float-point or integer types of default precisions:

a = 1.7
b = int(a)    # 1
c = float(a)  # 1.0

Casting vectors and matrices

Type casts applied to vectors/matrices are element-wise:

u = ti.Vector([2.3, 4.7])
v = int(u)              # ti.Vector([2, 4])
# If you are using ti.i32 as default_ip, this is equivalent to:
v = ti.cast(u, ti.i32)  # ti.Vector([2, 4])

Bit casting

使用 ti.bit_cast 将值比特转换为另一种数据类型。 基础位将保留在此转换中。 新类型的宽度必须与旧类型的宽度相同。 例如,不允许将 i32 转换成 f64。 请谨慎使用此操作。