Introduction
Type conversion includes implicit and explicit conversion. Implicit conversion is automatically performed by the system when types do not match. Explicit conversion is proactively performed by calling the type conversion API. The API converts the input data from the source type to the target type and returns the conversion result. The entire conversion process complies with the specified processing rules. The conversion result is affected by the rounding mode and saturation behavior. For details about the representation modes and rounding rules of floating-point numbers, see Function Usage.
Implicit Conversion
Implicit conversion refers to the behavior that the system automatically converts data from the source type to the target type without explicitly specifying the target type.
1 2 | int32_t a; a = 2.2f; // a = 2 |
Input Data Type |
Output Data Type |
Rounding Rules and Special Values |
||
|---|---|---|---|---|
Integer |
int8_t/uint8_t/int16_t/uint16_t/int32_t/uint32_t/int64_t/uint64_t |
Integer |
int8_t/uint8_t/int16_t/uint16_t/int32_t/uint32_t/int64_t/uint64_t |
Rounding complies with CAST_TRUNC. |
Floating-point variable |
float |
Integer |
int32_t/uint32_t/int64_t/uint64_t |
Rounding complies with CAST_TRUNC. When wide-range data is converted to narrow-range data:
|
half |
int32_t/uint32_t |
|||
bfloat16_t |
int32_t/uint32_t |
|||
Integer |
int32_t |
Floating-point variable |
float/half/bfloat16_t |
Rounding complies with CAST_RINT. When wide-range data is converted to narrow-range data:
|
uint32_t |
float/half/bfloat16_t |
|||
int64_t |
float |
|||
uint64_t |
float |
|||
Floating-point variable |
float |
Floating-point variable |
half/bfloat16_t |
Rounding complies with CAST_RINT. When wide-range data is converted to narrow-range data:
|
half |
float/bfloat16_t |
|||
bfloat16_t |
float/half |
|||
Example implicit conversions are as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | // Convert int8_t to uint8_t. int8_t a = -100; uint8_t b = a; // b = 156 // Convert half to int32_t. half a = 60000.6; int32_t b = a; // b = 60000 // Convert int32_t to half. int32_t a = 100000; half b = a; // b = inf, 100000 is out of the range that can be represented by the half type. // Convert float to half. float a = -100000.0f; half b = a; // b = -inf, -100000.0f is out of the range that can be represented by the half type. |
Rounding Mode
The rounding mode controls how the precision loss is handled during conversions.
Rounding Mode |
Description |
API Name Format |
|---|---|---|
CAST_RINT |
Rounding to the nearest even number (banker's rounding) |
srctype2dsttype_rn |
CAST_FLOOR |
Rounding down |
SrcType2DstType_rd |
CAST_CEIL |
Rounding up |
srctype2dsttype_ru |
CAST_ROUND |
Rounding off |
srctype2dsttype_rna |
CAST_TRUNC |
Rounding towards zero |
srctype2dsttype_rz |
CAST_ODD |
Rounding to the nearest odd number |
srctype2dsttype_ro |
CAST_HYBRID |
Hybrid rounding mode. This stochastic rounding mode is currently used exclusively when the output is of hi8 type. |
srctype2dsttype_rh |
This table describes the API name format corresponding to each input mode. In the format, srctype indicates the source operand type, and dsttype indicates the output target type. For example, if the float type is converted to the half type and the CAST_RINT mode is used for rounding, the API name is __float2half_rn.
Saturation Behavior
The saturation behavior controls how the special values such as nan and inf, and the results that are out of the representable range of the target type are handled.
Mode |
Description |
API Name Format |
|---|---|---|
Non-saturation mode |
Default mode.
|
srctype2dsttype_r[xx] |
Saturation mode |
In saturation mode:
|
srctype2dsttype_r[xx]_sat |
Methods of Controlling Saturation Behaviors
The saturation behavior is controlled by bit[60] and bit[48] of the CTRL register and API functions. For details about how to set the CTRL register in SIMD and SIMT programming scenarios, see SetCtrlSpr(ISASI). For SIMT programming, the CTRL register is not supported.
When wide-range data is converted to narrow-range data and the target type of the conversion is not float, including conversions such as float to half, float to bfloat16_t, bfloat16_t to half, and float or half to hifloat8_t, fp8_e4m3fn_t, or fp8_e5m2_t, the saturation behavior of the API is affected by bit[60] and bit[48] of the hardware register CTRL. The specific behaviors are as follows:
- When bit[60] of the CTRL register is 0, the saturation behavior is independently controlled by the API.
- The conversion result of the API with the suffix __sat is in saturation mode.
- The conversion result of the API without the suffix __sat is in non-saturation mode.
- When bit[60] of the CTRL register is 1, the saturation behavior is globally controlled by bit[48] of the CTRL register.
- When bit [48] of the CTRL register is 1, the conversion result of the API is in non-saturation mode.
- When bit[48] of the CTRL register is 0, the conversion result of the API is in saturation mode.
Bit[60] of CTRL |
Bit[48] of CTRL |
API Name Format |
Final Saturation Behavior |
|---|---|---|---|
0 |
/ |
Without __sat |
Non-saturation |
1 |
1 |
/ |
Non-saturation |
0 |
/ |
__sat |
Saturation |
1 |
0 |
/ |
Saturation |
The saturation behavior is only controlled by bit[48] of the CTRL register in the following two scenarios:
- Conversion from narrow-range data to wide-range data, where the target operand type is not float, that is, conversion from half to bfloat16_t and from hifloat8_t to half.
- Conversion from half to half and from bfloat16_t to bfloat16_t.
The specific behaviors are as follows:
- When bit [48] of the CTRL register is 1, the conversion result of the API is in non-saturation mode.
- When bit[48] of the CTRL register is 0, the conversion result of the API is in saturation mode.
Bit[60] of CTRL |
Bit[48] of CTRL |
Final Saturation Behavior |
|---|---|---|
/ |
1 |
Non-saturation |
/ |
0 |
Saturation |
If the target type is float, all type conversion APIs only support the non-saturation mode. When a floating-point number is converted to an integer, the conversion result is in saturation mode.
Examples of Data Type Conversion Rules
Input Data Type |
Output Data Type |
Example of Precision Conversion Rule |
|---|---|---|
float |
float |
Rounds src based on the rounding mode (a precision conversion mode, see Table 2) and saves the result in float format in dst. For example, in the case of input 0.5: The output is 0.0 in CAST_RINT mode, 0.0 in CAST_FLOOR mode, 1.0 in CAST_CEIL mode, 1.0 in CAST_ROUND mode, and 0.0 in CAST_TRUNC mode. |
half |
Example 1: For input 0.5 + 2-12, it is represented as 2-1 * (1 + 2-11) in float type, meaning that E = –1 + 127 = 126, and M = 2-11. The exponent bits of the half type can represent 2-1, meaning E = –1 + 15 = 14. However, the half type has only 10 mantissa bits. Therefore, rounding is required. In CAST_RINT mode, the result mantissa is 0000000000, E = 14, and M = 0. The final result is 0.5. In CAST_FLOOR mode, the result mantissa is 0000000000, E = 14, and M = 0. The final result is 0.5. In CAST_CEIL mode, the result mantissa is 0000000001, E = 14, and M = 2-10. The final result is 0.5 + 2-11. In CAST_ROUND mode, the result mantissa is 0000000001, E = 14, and M = 2-10. The final result is 0.5 + 2-11. In CAST_TRUNC mode, the result mantissa is 0000000000, E = 14, and M = 0. The final result is 0.5. In CAST_ODD mode, the result mantissa is 0000000001, E = 14, and M = 2-10. The final result is 0.5 + 2-11. For details about the final saturation behavior of float-to-half conversion, see Table 4. Example 2: For input inf, the output is 65504 in saturation mode, and inf in non-saturation mode. Example 3: For input -inf, the output is -65504 in saturation mode, and -inf in non-saturation mode. Example 4: For input nan, the output is 0 in saturation mode, and nan in non-saturation mode. |
|
bfloat16_t |
Example 1: For input 0.5 + 2-9 + 2-11, it is represented as 2–1 * (1 + 2–8 + 2–10) in float format, meaning that E = –1 + 127 = 126 and M = 2–8 + 2–10. The number of exponent bits of bfloat16_t is the same as that of float, that is, E = 126. However, bfloat16_t has only 7 mantissa bits. Therefore, rounding is required. In CAST_RINT mode, the result mantissa is 0000001, E = 126, and M = 2–7. The final result is 0.5 + 2–8. In CAST_FLOOR mode, the result mantissa is 0000000, E = 126, and M = 0. The final result is 0.5. In CAST_CEIL mode, the result mantissa is 0000001, E = 126, and M = 2–7. The final result is 0.5 + 2–8. In CAST_ROUND mode, the result mantissa is 0000001, E = 126, and M = 2–7. The final result is 0.5 + 2–8. In CAST_TRUNC mode, the result mantissa is 0000000, E = 126, and M = 0. The final result is 0.5. For details about the final saturation behavior of float-to-bfloat16_t conversion, see Table 4. Example 2: For input inf, the output is about 3.39*1038 in saturation mode, and inf in non-saturation mode. Example 3: For input -inf, the output is about -3.39*1038 in saturation mode, and -inf in non-saturation mode. Example 3: For input nan, the output is 0 in saturation mode, and nan in non-saturation mode. |
|
int32_t |
Example 1: For input 222 + 0.5, the output is 222 in CAST_RINT mode, 222 in CAST_FLOOR mode, 222 + 1 in CAST_CEIL mode, 222 + 1 in CAST_ROUND mode, and 222 in CAST_TRUNC mode. Example 2: For input inf, the output is 231-1. Example 3: For input -inf, the output is 2-31. Example 4: For input nan, the output is 0. |
|
uint32_t |
Example 1: For input 222 + 0.5, the output is 222 in CAST_RINT mode, 222 in CAST_FLOOR mode, 222 + 1 in CAST_CEIL mode, 222 + 1 in CAST_ROUND mode, and 222 in CAST_TRUNC mode. Example 2: For input inf, the output is 232-1. Example 3: For input -inf, the output is 0. Example 4: For input nan, the output is 0. |
|
int64_t |
Example 1: For input 222 + 0.5, the output is 222 in CAST_RINT mode, 222 in CAST_FLOOR mode, 222 + 1 in CAST_CEIL mode, 222 + 1 in CAST_ROUND mode, and 222 in CAST_TRUNC mode. Example 2: For input inf, the output is 232-1. Example 3: For input -inf, the output is 0. Example 4: For input nan, the output is 0. |
|
uint64_t |
Example 1: For input 222 + 0.5, the output is 222 in CAST_RINT mode, 222 in CAST_FLOOR mode, 222 + 1 in CAST_CEIL mode, 222 + 1 in CAST_ROUND mode, and 222 in CAST_TRUNC mode. Example 2: For input inf, the output is 264-1. Example 3: For input -inf, the output is 0. Example 4: For input nan, the output is 0. |
|
hifloat8_t |
Rounds src based on the rounding mode and saves the result in hifloat8_t format in dst (the overflow part is saturated). For example, if the input is 1.75, the output is 2 in CAST_ROUND mode. For details about the output in CAST_HYBRID mode, see Table 9. |
|
fp8_e4m3fn_t |
Rounds src based on the rounding mode and saves the result in fp8_e4m3fn_t format in dst (the overflow part is saturated). For example, if the input is 2.5, the output is 2 in CAST_RINT mode. |
|
fp8_e5m2_t |
Rounds src based on the rounding mode and saves the result in fp8_e5m2_t format in dst (the overflow part is saturated). For example, if the input is 2.5, the output is 2 in CAST_RINT mode. |
|
half |
half |
Rounds src based on the rounding mode and saves the result in half format in dst. For example, in the case of input 0.5: The output is 0.0 in CAST_RINT mode, 0.0 in CAST_FLOOR mode, 1.0 in CAST_CEIL mode, 1.0 in CAST_ROUND mode, and 0.0 in CAST_TRUNC mode. |
float |
There is no precision conversion issue, and the rounding mode does not take effect. Example 1: For input 1.5 - 2-10, the output is 1.5 - 2-10. The half-to-float conversion only supports non-saturation behaviors. Example 2: For input inf, the output is inf. Example 3: For input -inf, the output is -inf. Example 4: For input nan, the output is nan. |
|
bfloat16_t |
Example 1: For input 0.5 + 2-9 + 2-11, it is represented as 2–1 * (1 + 2–8 + 2–10) in half format, meaning that E = -1 + 15 = 14 and M = 2-8 + 2-10. The exponent bits of the bfloat16_t type can represent 2-1, meaning E = -1 + 127 = 126. However, the bfloat16_t type has only 7 mantissa bits. Therefore, rounding is required. In CAST_RINT mode, the result mantissa is 0000001, E = 126, and M = 2–7. The final result is 0.5 + 2-8. In CAST_FLOOR mode, the result mantissa is 0000000, E = 126, and M = 0. The final result is 0.5. In CAST_CEIL mode, the result mantissa is 0000001, E = 126, and M = 2–7. The final result is 0.5 + 2–8. In CAST_ROUND mode, the result mantissa is 0000001, E = 126, and M = 2–7. The final result is 0.5 + 2–8. In CAST_TRUNC mode, the result mantissa is 0000000, E = 126, and M = 0. The final result is 0.5. For details about the final saturation behavior of half-to-bfloat16_t conversion, see Table 5. Example 2: For input inf, the output is about 3.39*1038 in saturation mode, and inf in non-saturation mode. Example 3: For input -inf, the output is about -3.39*1038 in saturation mode, and -inf in non-saturation mode. Example 4: For input nan, the output is 0 in saturation mode, and nan in non-saturation mode. |
|
int32_t |
Example 1: For input 29 + 0.5, the output is 29 in CAST_RINT mode, 29 in CAST_FLOOR mode, 29 + 1 in CAST_CEIL mode, 29 + 1 in CAST_ROUND mode, and 29 in CAST_TRUNC mode. Example 2: For input inf, the output is 231-1. Example 3: For input -inf, the output is 2-31. Example 4: For input nan, the output is 0. |
|
uint32_t |
Example 1: For input 29 + 0.5, the output is 29 in CAST_RINT mode, 29 in CAST_FLOOR mode, 29 + 1 in CAST_CEIL mode, 29 + 1 in CAST_ROUND mode, and 29 in CAST_TRUNC mode. Example 2: For input inf, the output is 232-1. Example 3: For input -inf, the output is 0. Example 4: For input nan, the output is 0. |
|
hifloat8_t |
Rounds src based on the rounding mode and saves the result in hifloat8_t format in dst (the overflow part is saturated). For example, in the case of input 1.75: The output is 2 in CAST_ROUND mode. For details about the output in CAST_HYBRID mode, see Table 10. |
|
bfloat16_t |
bfloat16_t |
Rounds src based on the rounding mode and saves the result in bfloat16_t format in dst. For example, in the case of input 0.5: The output is 0.0 in CAST_RINT mode, 0.0 in CAST_FLOOR mode, 1.0 in CAST_CEIL mode, 1.0 in CAST_ROUND mode, and 0.0 in CAST_TRUNC mode. |
float |
There is no precision conversion issue, and the rounding mode does not take effect. Example 1: For input 1.5 - 2-6, the output is 1.5 - 2-6. The bfloat16_t-to-float conversion only supports non-saturation behaviors. Example 2: For input inf, the output is inf. Example 3: For input -inf, the output is -inf. Example 4: For input nan, the output is nan. |
|
half |
Example 1: For input 1.5 - 2-6, the output is 1.5 - 2-6. For details about the final saturation behavior of bfloat16-to-half conversion, see Table 4. Example 2: For input inf, the output is 65504 in saturation mode, and inf in non-saturation mode. Example 3: For input -inf, the output is -65504 in saturation mode, and -inf in non-saturation mode. Example 3: For input nan, the output is 0 in saturation mode, and nan in non-saturation mode. |
|
int32_t |
Example 1: For input 26 + 0.5, the output is 26 in CAST_RINT mode, 26 in CAST_FLOOR mode, 26 + 1 in CAST_CEIL mode, 26 + 1 in CAST_ROUND mode, and 26 in CAST_TRUNC mode. Example 2: For input inf, the output is 231-1. Example 3: For input -inf, the output is 2-31. Example 4: For input nan, the output is 0. |
|
uint32_t |
Example 1: For input 26 + 0.5, the output is 26 in CAST_RINT mode, 26 in CAST_FLOOR mode, 26 + 1 in CAST_CEIL mode, 26 + 1 in CAST_ROUND mode, and 26 in CAST_TRUNC mode. Example 2: For input inf, the output is 232-1. Example 3: For input -inf, the output is 0. Example 4: For input nan, the output is 0. |
|
hifloat8_t |
float |
Stores src in dst in float format. There is no precision conversion issue, and no rounding mode is involved. For example, if the input is 2, the output is 2. |
half |
Stores src in dst in half format. There is no precision conversion issue, and no rounding mode is involved. For example, if the input is 2, the output is 2. |
|
fp8_e4m3fn_t |
float |
Stores src in dst in float format. There is no precision conversion issue, and no rounding mode is involved. For example, if the input is 2, the output is 2. |
fp8_e5m2_t |
float |
Stores src in dst in float format. There is no precision conversion issue, and no rounding mode is involved. For example, if the input is 2, the output is 2. |
int32_t |
float |
Example 1: For input 225 + 3, it is represented as 225 * (1 + 2-24 + 2-25) in float type, meaning that E = 25 + 127 = 152 and M = 2-24 + 2-25. However, float has only 23 mantissa bits. Therefore, rounding is required. In CAST_RINT mode, the result mantissa is 00000000000000000000001, E = 152, and M = 2-23. The final result is 225 + 4. In CAST_FLOOR mode, the result mantissa is 00000000000000000000000, E = 152, and M = 0. The final result is 225. In CAST_CEIL mode, the result mantissa is 00000000000000000000001, E = 152, and M = 2-23. The final result is 225 + 4. In CAST_ROUND mode, the result mantissa is 00000000000000000000001, E = 152, and M = 2-23. The final result is 225 + 4. In CAST_TRUNC mode, the result mantissa is 00000000000000000000000, E = 152, and M = 0. The final result is 225. |
half |
Example 1: For input 212 + 3, it is represented as 212 *(1 + 2-11 + 2-12) in half type, meaning that E = 12 + 15 = 27 and M = 2-11 + 2-12. However, half has only 10 mantissa bits. Therefore, rounding is required. In CAST_RINT mode, the result mantissa is 0000000001, E = 27, and M = 2-10. The final result is 212 + 4. In CAST_FLOOR mode, the result mantissa is 0000000000, E = 27, and M = 0. The final result is 212. In CAST_CEIL mode, the result mantissa is 0000000001, E = 27, and M = 2-10. The final result is 212 + 4. In CAST_ROUND mode, the result mantissa is 0000000001, E = 27, and M = 2-10. The final result is 212 + 4. In CAST_TRUNC mode, the result mantissa is 0000000000, E = 27, and M = 0. The final result is 212. Example 2: For input 231 - 1, the return value is 65504.0 in SAT mode and inf in NO_SAT mode. Example 3: For input -231, the return value is -65504.0 in SAT mode and -inf in NO_SAT mode. |
|
bfloat16_t |
Example 1: For input 29 + 3, it is represented as 29 *(1 + 2-8 + 2-9) in bfloat16_t type, meaning that E = 9 + 127 = 136 and M = 2-8 + 2-9. However, bfloat16_t has only 7 mantissa bits. Therefore, rounding is required. In CAST_RINT mode, the result mantissa is 0000001, E = 136, and M = 2-7. The final result is 29 + 4. In CAST_FLOOR mode, the result mantissa is 0000000, E = 136, and M = 0. The final result is 29. In CAST_CEIL mode, the result mantissa is 0000001, E = 136, and M = 2-7. The final result is 29 + 4. In CAST_ROUND mode, the result mantissa is 0000001, E = 136, and M = 2-7. The final result is 29 + 4. In CAST_TRUNC mode, the result mantissa is 0000000, E = 136, and M = 0. The final result is 29. |
|
uint32_t |
float |
Example 1: For input 225 + 3, it is represented as 225 * (1 + 2-24 + 2-25) in float type, meaning that E = 25 + 127 = 152 and M = 2-24 + 2-25. However, float has only 23 mantissa bits. Therefore, rounding is required. In CAST_RINT mode, the result mantissa is 00000000000000000000001, E = 152, and M = 2-23. The final result is 225 + 4. In CAST_FLOOR mode, the result mantissa is 00000000000000000000000, E = 152, and M = 0. The final result is 225. In CAST_CEIL mode, the result mantissa is 00000000000000000000001, E = 152, and M = 2-23. The final result is 225 + 4. In CAST_ROUND mode, the result mantissa is 00000000000000000000001, E = 152, and M = 2-23. The final result is 225 + 4. In CAST_TRUNC mode, the result mantissa is 00000000000000000000000, E = 152, and M = 0. The final result is 225. |
half |
Example 1: For input 212 + 3, it is represented as 212 *(1 + 2-11 + 2-12) in half type, meaning that E = 12 + 15 = 27 and M = 2-11 + 2-12. However, half has only 10 mantissa bits. Therefore, rounding is required. In CAST_RINT mode, the result mantissa is 0000000001, E = 27, and M = 2-10. The final result is 212 + 4. In CAST_FLOOR mode, the result mantissa is 0000000000, E = 27, and M = 0. The final result is 212. In CAST_CEIL mode, the result mantissa is 0000000001, E = 27, and M = 2-10. The final result is 212 + 4. In CAST_ROUND mode, the result mantissa is 0000000001, E = 27, and M = 2-10. The final result is 212 + 4. In CAST_TRUNC mode, the result mantissa is 0000000000, E = 27, and M = 0. The final result is 212. Example 2: For input 232 - 1, the return value is 65504.0 in SAT mode and inf in NO_SAT mode. |
|
bfloat16_t |
Example 1: For input 29 + 3, it is represented as 29 *(1 + 2-8 + 2-9) in bfloat16_t type, meaning that E = 9 + 127 = 136 and M = 2-8 + 2-9. However, bfloat16_t has only 7 mantissa bits. Therefore, rounding is required. In CAST_RINT mode, the result mantissa is 0000001, E = 136, and M = 2-7. The final result is 29 + 4. In CAST_FLOOR mode, the result mantissa is 0000000, E = 136, and M = 0. The final result is 29. In CAST_CEIL mode, the result mantissa is 0000001, E = 136, and M = 2-7. The final result is 29 + 4. In CAST_ROUND mode, the result mantissa is 0000001, E = 136, and M = 2-7. The final result is 29 + 4. In CAST_TRUNC mode, the result mantissa is 0000000, E = 136, and M = 0. The final result is 29. |
|
int64_t |
float |
Example 1: For input 225 + 3, it is represented as 225 * (1 + 2-24 + 2-25) in float type, meaning that E = 25 + 127 = 152 and M = 2-24 + 2-25. However, float has only 23 mantissa bits. Therefore, rounding is required. In CAST_RINT mode, the result mantissa is 00000000000000000000001, E = 152, and M = 2-23. The final result is 225 + 4. In CAST_FLOOR mode, the result mantissa is 00000000000000000000000, E = 152, and M = 0. The final result is 225. In CAST_CEIL mode, the result mantissa is 00000000000000000000001, E = 152, and M = 2-23. The final result is 225 + 4. In CAST_ROUND mode, the result mantissa is 00000000000000000000001, E = 152, and M = 2-23. The final result is 225 + 4. In CAST_TRUNC mode, the result mantissa is 00000000000000000000000, E = 152, and M = 0. The final result is 225. |
uint64_t |
float |
Example 1: For input 225 + 3, it is represented as 225 * (1 + 2-24 + 2-25) in float type, meaning that E = 25 + 127 = 152 and M = 2-24 + 2-25. However, float has only 23 mantissa bits. Therefore, rounding is required. In CAST_RINT mode, the result mantissa is 00000000000000000000001, E = 152, and M = 2-23. The final result is 225 + 4. In CAST_FLOOR mode, the result mantissa is 00000000000000000000000, E = 152, and M = 0. The final result is 225. In CAST_CEIL mode, the result mantissa is 00000000000000000000001, E = 152, and M = 2-23. The final result is 225 + 4. In CAST_ROUND mode, the result mantissa is 00000000000000000000001, E = 152, and M = 2-23. The final result is 225 + 4. In CAST_TRUNC mode, the result mantissa is 00000000000000000000000, E = 152, and M = 0. The final result is 225. |