Casting and Type Promotion
This section is on data type casting and implicit type promotion.
Type Casting
You can use the function cast
to explicitly change the element type of a vector:
// a = [0, 1, 2, 3]
kf::vec<int, 4> a = kf::range<int, 4>();
// b = [0, 1, 2, 3]
kf::vec<short, 4> b = kf::cast<short>(a);
// c = [0.0f, 1.0f, 2.0f, 3.0f]
kf::vec<float, 4> c = kf::cast<float>(a);
// d = [false, true, true, true]
kf::vec<bool, 4> d = kf::cast<bool>(a);
Kernel Float allows implicit type conversions between vector types only for widening casts (i.e., converting a smaller type into a larger type).
// a = [0, 1, 2, 3]
kf::vec<int, 4> a = kf::range<int, 4>();
// This is allowed: int -> long
kf::vec<long, 4> b = a;
// This is also allowed: int -> float
kf::vec<float, 4> c = a;
Kernel Float does not perform implicit conversion for narrowing casts; this requires an explicit cast:
// a = [0, 1, 2, 3]
kf::vec<double, 4> a = kf::range<double, 4>();
// This is NOT allowed, use `kf::cast<float>(a)`
kf::vec<float, 4> b = a; // ERROR
// This is NOT allowed, use `kf::cast<int>(a)`
kf::vec<int, 4> c = a; // ERROR
// This is NOT allowed, use `kf::cast<bool>(a)`
kf::vec<bool, 4> d = a; // ERROR
Alternatively, it is possible to use kf::cast_to
on the left side of the assignment to perform a cast:
// a = [0, 1, 2, 3]
kf::vec<double, 4> a = kf::range<double, 4>();
// Define b
kf::vec<float, 4> b;
// This is equivalent to `b = kf::cast<float>(a)`
kf::cast_to(b) = a;
Type Promotion
When performing operations between vectors of different types or sizes, Kernel Float automatically promotes types to ensure compatibility. This process is known as type promotion.
Consider the following example. What should the type of c
be in this case?
kf::vec<float, 4> a = {1.0f, 2.0f, 3.0f, 4.0f};
kf::vec<double, 4> b = {10.0, 20.0, 30.0, 40.0};
kf::vec<???, 4> c = a + b;
Another example is the following snippet. Again, what should the type of c
be?
kf::vec<float, 4> x = {1.0f, 2.0f, 3.0f, 4.0f};
int factor = 2;
kf::vec<???, ???> c = x * factor;
How Type Promotion Works
Type promotion in Kernel Float unifies arguments for binary (and ternary) operations through the following steps:
Vectorization: Each non-vector argument is converted into a vector using the
into_vec
function.Length Unification: All arguments must have the same length N or length 1. Vectors of length 1 are broadcasted to match length N.
Type Unification: The element types are promoted to a common type based on the following promotion rules.
Promotion Rules
The rules for element type promotion in Kernel Float are slightly different from standard C++. Here’s a summary:
Boolean Types: If one of the types is bool, the result type is the other type.
Floating-Point and Integer: If one type is floating-point and the other is an integer (signed or unsigned), the result is the floating-point type.
Floating-Point Types: If both are floating-point types, the larger (wider) type is chosen. Exception: Combining half and bfloat16 results in float.
Integer Types: If both are integers of the same signedness (both signed or both unsigned), the larger type is chosen. Combining a signed integer and an unsigned integer is not allowed.
Overview
The following table summarizes the type promotion rules. The labels used are:
b
: booleaniN
: signed integer ofN
bits (e.g.,int
,long
)uN
: unsigned integer ofN
bits (e.g.,unsigned int
,size_t
)fN
: floating-point type ofN
bits (e.g.,float
,double
)bf16
: bfloat16 floating-point format.
b |
i8 |
i16 |
i32 |
i64 |
u8 |
u16 |
u32 |
u64 |
f8 |
f16 |
bf16 |
f32 |
f64 |
|
b |
b |
i8 |
i16 |
i32 |
i64 |
u8 |
u16 |
u32 |
u64 |
f8 |
f16 |
bf16 |
f32 |
f64 |
i8 |
i8 |
i8 |
i16 |
i32 |
i64 |
x |
x |
x |
x |
f8 |
f16 |
bf16 |
f32 |
f64 |
i16 |
i16 |
i16 |
i16 |
i32 |
i64 |
x |
x |
x |
x |
f8 |
f16 |
bf16 |
f32 |
f64 |
i32 |
i32 |
i32 |
i32 |
i32 |
i64 |
x |
x |
x |
x |
f8 |
f16 |
bf16 |
f32 |
f64 |
i64 |
i64 |
i64 |
i64 |
i64 |
i64 |
x |
x |
x |
x |
f8 |
f16 |
bf16 |
f32 |
f64 |
u8 |
u8 |
x |
x |
x |
x |
u8 |
u16 |
u32 |
u64 |
f8 |
f16 |
bf16 |
f32 |
f64 |
u16 |
u16 |
x |
x |
x |
x |
u16 |
u16 |
u32 |
u64 |
f8 |
f16 |
bf16 |
f32 |
f64 |
u32 |
u32 |
x |
x |
x |
x |
u32 |
u32 |
u32 |
u64 |
f8 |
f16 |
bf16 |
f32 |
f64 |
u64 |
u64 |
x |
x |
x |
x |
u64 |
u64 |
u64 |
u64 |
f8 |
f16 |
bf16 |
f32 |
f64 |
f8 |
f8 |
f8 |
f8 |
f8 |
f8 |
f8 |
f8 |
f8 |
f8 |
f8 |
f16 |
bf16 |
f32 |
f64 |
f16 |
f16 |
f16 |
f16 |
f16 |
f16 |
f16 |
f16 |
f16 |
f16 |
f16 |
f16 |
f32 |
f32 |
f64 |
bf16 |
bf16 |
bf16 |
bf16 |
bf16 |
bf16 |
bf16 |
bf16 |
bf16 |
bf16 |
bf16 |
f32 |
bf16 |
f32 |
f64 |
f32 |
f32 |
f32 |
f32 |
f32 |
f32 |
f32 |
f32 |
f32 |
f32 |
f32 |
f32 |
f32 |
f32 |
f64 |
f64 |
f64 |
f64 |
f64 |
f64 |
f64 |
f64 |
f64 |
f64 |
f64 |
f64 |
f64 |
f64 |
f64 |
f64 |
.. csv-table:: Type Promotion Rules. :file: promotion_table.csv