Add $$select. "--fp-math" options. Fixed issue with accidentally silent error on failed vector conversions.

This commit is contained in:
Christoffer Lerno
2023-09-08 09:03:00 +02:00
committed by Christoffer Lerno
parent b894e5be69
commit 4ef74a1205
23 changed files with 366 additions and 162 deletions

View File

@@ -2,6 +2,10 @@ module std::core::values;
macro TypeKind @typekind(#value) @builtin => $typeof(#value).kindof;
macro bool @typeis(#value, $Type) @builtin => $typeof(#value).typeid == $Type.typeid;
/**
* Return true if two values have the same type before any conversions.
**/
macro bool @is_same_type(#value1, #value2) => $typeof(#value1).typeid == $typeof(#value2).typeid;
macro bool @is_bool(#value) => types::is_bool($typeof(#value));
macro bool @is_int(#value) => types::is_int($typeof(#value));
macro bool @convertable_to(#a, #b) => $checks($typeof(#b) x = #a);
@@ -9,6 +13,7 @@ macro bool @is_floatlike(#value) => types::is_floatlike($typeof(#value));
macro bool @is_float(#value) => types::is_float($typeof(#value));
macro bool @is_promotable_to_floatlike(#value) => types::is_promotable_to_floatlike($typeof(#value));
macro bool @is_promotable_to_float(#value) => types::is_promotable_to_float($typeof(#value));
macro bool @is_vector(#value) => types::is_vector($typeof(#value));
macro bool @is_same_vector_type(#value1, #value2) => types::is_same_vector_type($typeof(#value1), $typeof(#value2));
macro promote_int(x)
{

View File

@@ -80,6 +80,11 @@ enum RoundingMode : int
TOWARD_NEG_INFINITY
}
fault MathError
{
OVERFLOW,
}
fault MatrixError
{
MATRIX_INVERSE_DOESNT_EXIST,
@@ -545,6 +550,23 @@ macro normalize(x) @private
return x * (1 / len);
}
/**
* Use a mask to select values from either "then" or "else" vectors.
*
* @param mask "The mask to use for the select, 'true' will pick the then_value, 'false' the else_value"
* @param then_value "The vector to get elements from where the mask is 'true'"
* @param else_value "The vector to get elements from where the mask is 'false'"
* @require values::@is_vector(then_value) && values::@is_vector(else_value) "'Then' and 'else' must be vectors."
* @require values::@is_same_type(then_value, else_value) "'Then' and 'else' vectors must be of the same type."
* @require then_value.len == mask.len "Mask and selected vectors must be of the same width."
*
* @return "a vector of the same type as then/else"
**/
macro select(bool[<*>] mask, then_value, else_value)
{
return $$select(mask, then_value, else_value);
}
macro float float.ceil(float x) => $$ceil(x);
macro float float.clamp(float x, float lower, float upper) => $$max(lower, $$min(x, upper));
macro float float.copysign(float mag, float sgn) => $$copysign(mag, sgn);
@@ -798,52 +820,82 @@ macro char char.sat_add(char x, char y) => $$sat_add(x, y);
macro char char.sat_sub(char x, char y) => $$sat_sub(x, y);
macro char char.sat_mul(char x, char y) => $$sat_mul(x, y);
macro char char.sat_shl(char x, char y) => $$sat_shl(x, y);
macro char! char.overflow_add(char x, char y) => overflow_add_helper(x, y);
macro char! char.overflow_sub(char x, char y) => overflow_sub_helper(x, y);
macro char! char.overflow_mul(char x, char y) => overflow_mul_helper(x, y);
macro ichar ichar.sat_add(ichar x, ichar y) => $$sat_add(x, y);
macro ichar ichar.sat_sub(ichar x, ichar y) => $$sat_sub(x, y);
macro ichar ichar.sat_mul(ichar x, ichar y) => $$sat_mul(x, y);
macro ichar ichar.sat_shl(ichar x, ichar y) => $$sat_shl(x, y);
macro ichar! ichar.overflow_add(ichar x, ichar y) => overflow_add_helper(x, y);
macro ichar! ichar.overflow_sub(ichar x, ichar y) => overflow_sub_helper(x, y);
macro ichar! ichar.overflow_mul(ichar x, ichar y) => overflow_mul_helper(x, y);
macro ushort ushort.sat_add(ushort x, ushort y) => $$sat_add(x, y);
macro ushort ushort.sat_sub(ushort x, ushort y) => $$sat_sub(x, y);
macro ushort ushort.sat_mul(ushort x, ushort y) => $$sat_mul(x, y);
macro ushort ushort.sat_shl(ushort x, ushort y) => $$sat_shl(x, y);
macro ushort! ushort.overflow_add(ushort x, ushort y) => overflow_add_helper(x, y);
macro ushort! ushort.overflow_sub(ushort x, ushort y) => overflow_sub_helper(x, y);
macro ushort! ushort.overflow_mul(ushort x, ushort y) => overflow_mul_helper(x, y);
macro short short.sat_add(short x, short y) => $$sat_add(x, y);
macro short short.sat_sub(short x, short y) => $$sat_sub(x, y);
macro short short.sat_mul(short x, short y) => $$sat_mul(x, y);
macro short short.sat_shl(short x, short y) => $$sat_shl(x, y);
macro short! short.overflow_add(short x, short y) => overflow_add_helper(x, y);
macro short! short.overflow_sub(short x, short y) => overflow_sub_helper(x, y);
macro short! short.overflow_mul(short x, short y) => overflow_mul_helper(x, y);
macro uint uint.sat_add(uint x, uint y) => $$sat_add(x, y);
macro uint uint.sat_sub(uint x, uint y) => $$sat_sub(x, y);
macro uint uint.sat_mul(uint x, uint y) => $$sat_mul(x, y);
macro uint uint.sat_shl(uint x, uint y) => $$sat_shl(x, y);
macro uint! uint.overflow_add(uint x, uint y) => overflow_add_helper(x, y);
macro uint! uint.overflow_sub(uint x, uint y) => overflow_sub_helper(x, y);
macro uint! uint.overflow_mul(uint x, uint y) => overflow_mul_helper(x, y);
macro int int.sat_add(int x, int y) => $$sat_add(x, y);
macro int int.sat_sub(int x, int y) => $$sat_sub(x, y);
macro int int.sat_mul(int x, int y) => $$sat_mul(x, y);
macro int int.sat_shl(int x, int y) => $$sat_shl(x, y);
macro int! int.overflow_add(int x, int y) => overflow_add_helper(x, y);
macro int! int.overflow_sub(int x, int y) => overflow_sub_helper(x, y);
macro int! int.overflow_mul(int x, int y) => overflow_mul_helper(x, y);
macro ulong ulong.sat_add(ulong x, ulong y) => $$sat_add(x, y);
macro ulong ulong.sat_sub(ulong x, ulong y) => $$sat_sub(x, y);
macro ulong ulong.sat_mul(ulong x, ulong y) => $$sat_mul(x, y);
macro ulong ulong.sat_shl(ulong x, ulong y) => $$sat_shl(x, y);
macro ulong! ulong.overflow_add(ulong x, ulong y) => overflow_add_helper(x, y);
macro ulong! ulong.overflow_sub(ulong x, ulong y) => overflow_sub_helper(x, y);
macro ulong! ulong.overflow_mul(ulong x, ulong y) => overflow_mul_helper(x, y);
macro long long.sat_add(long x, long y) => $$sat_add(x, y);
macro long long.sat_sub(long x, long y) => $$sat_sub(x, y);
macro long long.sat_mul(long x, long y) => $$sat_mul(x, y);
macro long long.sat_shl(long x, long y) => $$sat_shl(x, y);
macro long! long.overflow_add(long x, long y) => overflow_add_helper(x, y);
macro long! long.overflow_sub(long x, long y) => overflow_sub_helper(x, y);
macro long! long.overflow_mul(long x, long y) => overflow_mul_helper(x, y);
macro uint128 uint128.sat_add(uint128 x, uint128 y) => $$sat_add(x, y);
macro uint128 uint128.sat_sub(uint128 x, uint128 y) => $$sat_sub(x, y);
macro uint128 uint128.sat_mul(uint128 x, uint128 y) => $$sat_mul(x, y);
macro uint128 uint128.sat_shl(uint128 x, uint128 y) => $$sat_shl(x, y);
macro uint128! uint128.overflow_add(uint128 x, uint128 y) => overflow_add_helper(x, y);
macro uint128! uint128.overflow_sub(uint128 x, uint128 y) => overflow_sub_helper(x, y);
macro uint128! uint128.overflow_mul(uint128 x, uint128 y) => overflow_mul_helper(x, y);
macro int128 int128.sat_add(int128 x, int128 y) => $$sat_add(x, y);
macro int128 int128.sat_sub(int128 x, int128 y) => $$sat_sub(x, y);
macro int128 int128.sat_mul(int128 x, int128 y) => $$sat_mul(x, y);
macro int128 int128.sat_shl(int128 x, int128 y) => $$sat_shl(x, y);
macro int128! int128.overflow_add(int128 x, int128 y) => overflow_add_helper(x, y);
macro int128! int128.overflow_sub(int128 x, int128 y) => overflow_sub_helper(x, y);
macro int128! int128.overflow_mul(int128 x, int128 y) => overflow_mul_helper(x, y);
/**
* @require values::@is_int(x) `The input must be an integer`
**/
@@ -986,4 +1038,25 @@ fn float _frexpf(float x, int* e)
i |= 0x3f000000u32;
return bitcast(i, float);
}
}
}
macro overflow_add_helper(x, y) @local
{
$typeof(x) res @noinit;
if ($$overflow_add(x, y, &res)) return MathError.OVERFLOW?;
return res;
}
macro overflow_sub_helper(x, y) @local
{
$typeof(x) res @noinit;
if ($$overflow_sub(x, y, &res)) return MathError.OVERFLOW?;
return res;
}
macro overflow_mul_helper(x, y) @local
{
$typeof(x) res @noinit;
if ($$overflow_mul(x, y, &res)) return MathError.OVERFLOW?;
return res;
}