diff --git a/README.md b/README.md index 9e58287..84313d2 100644 --- a/README.md +++ b/README.md @@ -12,21 +12,6 @@ - Seperate data types and functions in headers, support better compile speed, only include what needed - Find out more in `docs/coding_standards.md` -## TODOs -- Make all code use `float32_t` instead of `float`, for clearer size of floating-point number type -- Add project showcases -- API docs and usage docs -- Full clang extensions without deps on `__m128` for portable (on clang implementation) -- Make an example that use full advantages of clang vector extensions -- Benchmarking -- Maybe pattern solution for common problem in game/graphics development -- Make the first stable release -- Support more systems: left/right handed, vertical/horizontal field of view -- Choose namespace for primitives between: `int32`, `i32`, `int` (same with uint32, float32) - - `int32`: Same name with type `int32_t`, but too long - - `i32`: Short enough, not common in C, but maybe familiar for someones - - `int`: Short enough, common in C, but have no size - ## Import/include instructions - This library is headers only, you can easily import to your projects - Use scripts/vectormath.genie.lua (WIP) to import to projects that support GENie @@ -72,6 +57,6 @@ so other languages you should use the libraries written specifily for thoses lan - Is it stable yet? No. ## Meta -- Version: v0.3.0-dev +- Version: v0.5.0-dev - License: UNLICENSED - Copyright: MaiHD @ 2022 - 2024 diff --git a/changelogs/CHANGELOGS_v0.5.0-dev.md b/changelogs/CHANGELOGS_v0.5.0-dev.md new file mode 100644 index 0000000..b0ee8ef --- /dev/null +++ b/changelogs/CHANGELOGS_v0.5.0-dev.md @@ -0,0 +1,3 @@ +# VectorMath changelogs v0.5.0-dev +- Remove float32_t (impractical, float is IEEE-754, which have fixed size in definition) +- Docs for typedef of clang implementation \ No newline at end of file diff --git a/docs/TODOs.md b/docs/TODOs.md new file mode 100644 index 0000000..1d7b9dd --- /dev/null +++ b/docs/TODOs.md @@ -0,0 +1,9 @@ +## TODOs +- Add project showcases +- API docs and usage docs +- Full clang extensions without deps on `__m128` for portable (on clang implementation) +- Make an example that use full advantages of clang vector extensions +- Benchmarking +- Maybe pattern solution for common problem in game/graphics development +- Make the first stable release +- Support more systems: left/right handed, vertical/horizontal field of view \ No newline at end of file diff --git a/include/vectormath/scalarmath.h b/include/vectormath/scalarmath.h index 8a45de5..fdfbed6 100644 --- a/include/vectormath/scalarmath.h +++ b/include/vectormath/scalarmath.h @@ -58,13 +58,6 @@ // Types // ------------------------------------------------------------- -#ifndef __float32_t_defined -#define __float32_t_defined -typedef float float32_t; -#endif - -static_assert(sizeof(float32_t) == 4, "Unexpected `float32_t` size"); - // ------------------------------------------------------------- // Constants // ------------------------------------------------------------- @@ -95,36 +88,11 @@ constexpr float FLOAT_INV_TWO_PI = 1.0f / (3.141592653589f * 2.0f); constexpr float FLOAT_INV_HALF_PI = 1.0f / (3.141592653589f * 0.5f); constexpr float FLOAT_INV_THREE_HALF_PI = 1.0f / (3.141592653589f * 1.5f); -constexpr int32_t FLOAT32_DECIMAL_DIG = 9; // # of decimal digits of rounding precision -constexpr int32_t FLOAT32_DIG = 6; // # of decimal digits of precision -constexpr float32_t FLOAT32_EPSILON = 1.192092896e-07F; // smallest such that 1.0+FLT_EPSILON != 1.0 -constexpr float32_t FLOAT32_HAS_SUBNORM = 1; // type does support subnormal numbers -constexpr float32_t FLOAT32_GUARD = 0; -constexpr float32_t FLOAT32_MANT_DIG = 24; // # of bits in mantissa -constexpr float32_t FLOAT32_MAX = 3.402823466e+38F; // max value -constexpr float32_t FLOAT32_MAX_10_EXP = 38; // max decimal exponent -constexpr float32_t FLOAT32_MAX_EXP = 128; // max binary exponent -constexpr float32_t FLOAT32_MIN = 1.175494351e-38F; // min normalized positive value -constexpr int32_t FLOAT32_MIN_10_EXP = (-37); // min decimal exponent -constexpr int32_t FLOAT32_MIN_EXP = (-125); // min binary exponent -constexpr int32_t FLOAT32_NORMALIZE = 0; -constexpr int32_t FLOAT32_RADIX = 2; // exponent radix -constexpr float32_t FLOAT32_TRUE_MIN = 1.401298464e-45F; // min positive value - -constexpr float32_t FLOAT32_PI = 3.141592653589f; -constexpr float32_t FLOAT32_TWO_PI = 3.141592653589f * 2.0f; -constexpr float32_t FLOAT32_HALF_PI = 3.141592653589f * 0.5f; -constexpr float32_t FLOAT32_THREE_HALF_PI = 3.141592653589f * 1.5f; - -constexpr float32_t FLOAT32_INV_PI = 1.0f / (3.141592653589f * 1.0f); -constexpr float32_t FLOAT32_INV_TWO_PI = 1.0f / (3.141592653589f * 2.0f); -constexpr float32_t FLOAT32_INV_HALF_PI = 1.0f / (3.141592653589f * 0.5f); -constexpr float32_t FLOAT32_INV_THREE_HALF_PI = 1.0f / (3.141592653589f * 1.5f); - // ------------------------------------------------------------- // int32_t Functions // ------------------------------------------------------------- + /// Compute the sign of 'x' __forceinline int32_t int32_sign(int32_t x) { @@ -132,62 +100,73 @@ __forceinline int32_t int32_sign(int32_t x) return result; } + /// Get the smaller value __forceinline int32_t int32_min(int32_t x, int32_t y) { return x < y ? x : y; } + /// Get the larger value __forceinline int32_t int32_max(int32_t x, int32_t y) { return x > y ? x : y; } + /// Clamps the 'x' to the [min, max] __forceinline int32_t int32_clamp(int32_t x, int32_t min, int32_t max) { return x < min ? min : (x > max ? max : x); } + // ------------------------------------------------------------- // uint32_t Functions // ------------------------------------------------------------- + /// Get the smaller value __forceinline uint32_t uint32_min(uint32_t x, uint32_t y) { return x < y ? x : y; } + /// Get the larger value __forceinline uint32_t uint32_max(uint32_t x, uint32_t y) { return x > y ? x : y; } + /// Clamps the 'x' to the [min, max] __forceinline uint32_t uint32_clamp(uint32_t x, uint32_t min, uint32_t max) { return x < min ? min : (x > max ? max : x); } + // ------------------------------------------------------------- // float Functions // ------------------------------------------------------------- + /// Convert degrees to radians __forceinline float float_deg2rad(float degrees) { return degrees * FLOAT_PI / 180.0f; } + /// Convert radians to degrees __forceinline float float_rad2deg(float radians) { return radians * 180.0f / FLOAT_PI; } + /// Computes sign of 'x' __forceinline int32_t float_sign(float x) { @@ -200,90 +179,105 @@ __forceinline int32_t float_sign(float x) return int32_sign(cvt.i); } + /// Computes absolute value __forceinline float float_abs(float x) { return fabsf(x); } + /// Computes cosine __forceinline float float_cos(float x) { return cosf(x); } + /// Computes sine __forceinline float float_sin(float x) { return sinf(x); } + /// Computes tangent __forceinline float float_tan(float x) { return tanf(x); } + /// Computes hyperbolic cosine __forceinline float float_cosh(float x) { return coshf(x); } + /// Computes hyperbolic sine __forceinline float float_sinh(float x) { return sinhf(x); } + /// Computes hyperbolic tangent __forceinline float float_tanh(float x) { return tanhf(x); } + /// Computes inverse cosine __forceinline float float_acos(float x) { return acosf(x); } + /// Computes inverse sine __forceinline float float_asin(float x) { return asinf(x); } + /// Computes inverse tangent __forceinline float float_atan(float x) { return atanf(x); } + /// Computes inverse tangent with 2 args __forceinline float float_atan2(float x, float y) { return atan2f(x, y); } + /// Computes Euler number raised to the power 'x' __forceinline float float_exp(float x) { return expf(x); } + /// Computes 2 raised to the power 'x' __forceinline float float_exp2(float x) { return exp2f(x); } + /// Computes the base Euler number logarithm __forceinline float float_log(float x) { return logf(x); } + // Android polyfill for log2 and log2f #if defined(__ANDROID__) && defined(__ANDROID_API__) && __ANDROID_API__ < 18 __forceinline float log2f(float x) @@ -309,18 +303,21 @@ __forceinline float float_log2(float x) } #endif // Android polyfill for log2 and log2f + /// Computes the base 10 logarithm __forceinline float float_log10(float x) { return log10f(x); } + /// Computes the value of base raised to the power exponent __forceinline float float_pow(float x, float y) { return powf(x, y); } + /// Get the fractal part of floating point __forceinline float float_frac(float x) { @@ -328,84 +325,98 @@ __forceinline float float_frac(float x) return modff(x, &y); } + /// Computes the floating-point remainder of the division operation x/y __forceinline float float_fmod(float x, float y) { return fmodf(x, y); } + /// Computes the smallest integer value not less than 'x' __forceinline float float_ceil(float x) { return ceilf(x); } + /// Computes the largest integer value not greater than 'x' __forceinline float float_floor(float x) { return floorf(x); } + /// Computes the nearest integer value __forceinline float float_round(float x) { return roundf(x); } + /// Computes the nearest integer not greater in magnitude than 'x' __forceinline float float_trunc(float x) { return truncf(x); } + /// Get the smaller value __forceinline float float_min(float x, float y) { return x < y ? x : y; } + /// Get the larger value __forceinline float float_max(float x, float y) { return x > y ? x : y; } + /// Clamps the 'x' value to the [min, max]. __forceinline float float_clamp(float x, float min, float max) { return x < min ? min : (x > max ? max : x); } + /// Clamps the specified value within the range of 0 to 1 __forceinline float float_saturate(float x) { return float_clamp(x, 0.0f, 1.0f); } + /// Compares two values, returning 0 or 1 based on which value is greater. __forceinline float float_step(float y, float x) { return (float)(x >= y); } + /// Performs x linear interpolation. __forceinline float float_lerp(float x, float y, float s) { return x + (y - x) * s; } + /// Computes square root of 'x'. __forceinline float float_sqrt(float x) { return sqrtf(x); } + /// Computes inverse square root of 'x'. __forceinline float float_rsqrt(float x) { return 1.0f / sqrtf(x); } + /// Computes inverse square root of 'x', using FastInvSqrt algorithm. __forceinline float float_fast_rsqrt(float x) { @@ -422,6 +433,7 @@ __forceinline float float_fast_rsqrt(float x) return cvt.f; } + /// Compute x smooth Hermite interpolation /// @return: 0 if x <= min /// 1 if x >= max @@ -431,254 +443,9 @@ __forceinline float float_smoothstep(float min, float max, float x) return (float_clamp(x, min, max) - min) / (max - min); } -/// Test is two values are closely equal -__forceinline bool float_isclose(float x, float y) -{ - return fabsf(x - y) <= FLOAT_EPSILON; -} - -// ------------------------------------------------------------- -// float32_t Functions -// ------------------------------------------------------------- - -/// Convert degrees to radians -__forceinline float32_t float32_deg2rad(float32_t degrees) -{ - return degrees * FLOAT32_PI / 180.0f; -} - -/// Convert radians to degrees -__forceinline float32_t float32_rad2deg(float32_t radians) -{ - return radians * 180.0f / FLOAT32_PI; -} - - -/// Computes sign of 'x' -__forceinline int32_t float32_sign(float32_t x) -{ - union - { - float32_t f; - int32_t i; - } cvt; - cvt.f = x; - return int32_sign(cvt.i); -} - -/// Computes absolute value -__forceinline float32_t float32_abs(float32_t x) -{ - return fabsf(x); -} - -/// Computes cosine -__forceinline float32_t float32_cos(float32_t x) -{ - return cosf(x); -} - -/// Computes sine -__forceinline float32_t float32_sin(float32_t x) -{ - return sinf(x); -} - -/// Computes tangent -__forceinline float32_t float32_tan(float32_t x) -{ - return tanf(x); -} - -/// Computes hyperbolic cosine -__forceinline float32_t float32_cosh(float32_t x) -{ - return coshf(x); -} - -/// Computes hyperbolic sine -__forceinline float32_t float32_sinh(float32_t x) -{ - return sinhf(x); -} - -/// Computes hyperbolic tangent -__forceinline float32_t float32_tanh(float32_t x) -{ - return tanhf(x); -} - -/// Computes inverse cosine -__forceinline float32_t float32_acos(float32_t x) -{ - return acosf(x); -} - -/// Computes inverse sine -__forceinline float32_t float32_asin(float32_t x) -{ - return asinf(x); -} - -/// Computes inverse tangent -__forceinline float32_t float32_atan(float32_t x) -{ - return atanf(x); -} - -/// Computes inverse tangent with 2 args -__forceinline float32_t float32_atan2(float32_t x, float32_t y) -{ - return atan2f(x, y); -} - -/// Computes Euler number raised to the power 'x' -__forceinline float32_t float32_exp(float32_t x) -{ - return expf(x); -} - -/// Computes 2 raised to the power 'x' -__forceinline float32_t float32_exp2(float32_t x) -{ - return exp2f(x); -} - -/// Computes the base Euler number logarithm -__forceinline float32_t float32_log(float32_t x) -{ - return logf(x); -} - -// Android polyfill for log2 and log2f -#if defined(__ANDROID__) && defined(__ANDROID_API__) && __ANDROID_API__ < 18 -/// Computes the base 2 logarithm -__forceinline float32_t float32_log2(float32_t x) -{ - return (logf(x) / 0.693147180559945f); -} -#else -/// Computes the base 2 logarithm -__forceinline float32_t float32_log2(float32_t x) -{ - return log2f(x); -} -#endif // Android polyfill for log2 and log2f - -/// Computes the base 10 logarithm -__forceinline float32_t float32_log10(float32_t x) -{ - return log10f(x); -} - -/// Computes the value of base raised to the power exponent -__forceinline float32_t float32_pow(float32_t x, float32_t y) -{ - return powf(x, y); -} - -/// Get the fractal part of floating point -__forceinline float32_t float32_frac(float32_t x) -{ - float y; - return modff(x, &y); -} - -/// Computes the floating-point remainder of the division operation x/y -__forceinline float32_t float32_fmod(float32_t x, float32_t y) -{ - return fmodf(x, y); -} - -/// Computes the smallest integer value not less than 'x' -__forceinline float32_t float32_ceil(float32_t x) -{ - return ceilf(x); -} - -/// Computes the largest integer value not greater than 'x' -__forceinline float32_t float32_floor(float32_t x) -{ - return floorf(x); -} - -/// Computes the nearest integer value -__forceinline float32_t float32_round(float32_t x) -{ - return roundf(x); -} - -/// Computes the nearest integer not greater in magnitude than 'x' -__forceinline float32_t float32_trunc(float32_t x) -{ - return truncf(x); -} - -/// Get the smaller value -__forceinline float32_t float32_min(float32_t x, float32_t y) -{ - return x < y ? x : y; -} - -/// Get the larger value -__forceinline float32_t float32_max(float32_t x, float32_t y) -{ - return x > y ? x : y; -} - -/// Clamps the 'x' value to the [min, max]. -__forceinline float32_t float32_clamp(float32_t x, float32_t min, float32_t max) -{ - return x < min ? min : (x > max ? max : x); -} - -/// Clamps the specified value within the range of 0 to 1 -__forceinline float32_t float32_saturate(float32_t x) -{ - return float32_clamp(x, 0.0f, 1.0f); -} - -/// Compares two values, returning 0 or 1 based on which value is greater. -__forceinline float32_t float32_step(float32_t y, float32_t x) -{ - return (float32_t)(x >= y); -} - -/// Performs x linear interpolation. -__forceinline float32_t float32_lerp(float32_t x, float32_t y, float32_t s) -{ - return x + (y - x) * s; -} - -/// Computes square root of 'x'. -__forceinline float32_t float32_sqrt(float32_t x) -{ - return sqrtf(x); -} - -/// Computes inverse square root of 'x'. -__forceinline float32_t float32_rsqrt(float32_t x) -{ - return 1.0f / sqrtf(x); -} - -/// Computes inverse square root of 'x', using FastInvSqrt algorithm. -__forceinline float32_t float32_fast_rsqrt(float32_t x) -{ - return float_fast_rsqrt(x); -} - -/// Compute x smooth Hermite interpolation -/// @return: 0 if x <= min -/// 1 if x >= max -/// (0, 1) otherwise -__forceinline float32_t float32_smoothstep(float32_t min, float32_t max, float32_t x) -{ - return (float32_clamp(x, min, max) - min) / (max - min); -} /// Test is two values are closely equal -__forceinline bool float32_isclose(float32_t x, float32_t y) +__forceinline bool float_isclose(float x, float y) { return fabsf(x - y) <= FLOAT_EPSILON; } diff --git a/include/vectormath/vectormath_simd.h b/include/vectormath/vectormath_simd.h index fed9d54..3f1d1a4 100644 --- a/include/vectormath/vectormath_simd.h +++ b/include/vectormath/vectormath_simd.h @@ -612,7 +612,7 @@ __forceinline float vec3_distsqr(vec3 a, vec3 b) __forceinline vec3 vec3_normalize(vec3 v) { #ifndef VECTORMATH_USE_EXACT_PRECISION - return vec3_mul1(v, float32_fast_rsqrt(vec3_lensqr(v))); + return vec3_mul1(v, float_fast_rsqrt(vec3_lensqr(v))); #else const float lsqr = vec3_lensqr(v); if (lsqr > 0.0f) @@ -936,7 +936,7 @@ __forceinline float vec4_distsqr(vec4 a, vec4 b) __forceinline vec4 vec4_normalize(vec4 v) { #ifndef VECTORMATH_USE_EXACT_PRECISION - return vec4_mul1(v, float32_fast_rsqrt(vec4_lensqr(v))); + return vec4_mul1(v, float_fast_rsqrt(vec4_lensqr(v))); #else const float lsqr = vec4_lensqr(v); if (lsqr > 0.0f) diff --git a/include/vectormath/vectormath_types.h b/include/vectormath/vectormath_types.h index 5563a5b..1d43850 100644 --- a/include/vectormath/vectormath_types.h +++ b/include/vectormath/vectormath_types.h @@ -131,16 +131,66 @@ // ------------------------------------------------------------- #if VECTORMATH_ENABLE_CLANG_EXT +/// vec2 +/// 2D floating-point vector +/// Components are 32 bit fixed-size floating-point number +/// Struct Layout: [float x][float y] typedef float vec2 __attribute__((ext_vector_type(2), aligned(4))); + + +/// vec3 +/// 3D floating-point vector +/// Components are 32 bit fixed-size floating-point number +/// Struct Layout: [float x][float y][float z][float __unused] typedef float vec3 __attribute__((ext_vector_type(3), aligned(16))); + + +/// vec4 +/// 4D floating-point vector +/// Components are 32 bit fixed-size floating-point number +/// Struct Layout: [float x][float y][float z][float w] typedef float vec4 __attribute__((ext_vector_type(4), aligned(16))); + +/// ivec2 +/// 2D integer vector +/// Components are 32 bit fixed-size signed integer +/// Struct Layout: [int32_t x][int32_t y] typedef int32_t ivec2 __attribute__((ext_vector_type(2), aligned(4))); + + +/// ivec3 +/// 3D integer vector +/// Components are 32 bit fixed-size signed integer +/// Struct Layout: [int32_t x][int32_t y][int32_t z][int32_t __unused] typedef int32_t ivec3 __attribute__((ext_vector_type(3), aligned(16))); + + +/// ivec4 +/// 4D integer vector +/// Components are 32 bit fixed-size signed integer +/// Struct Layout: [int32_t x][int32_t y][int32_t z][int32_t w] typedef int32_t ivec4 __attribute__((ext_vector_type(4), aligned(16))); + +/// uvec2 +/// 2D integer vector +/// Components are 32 bit fixed-size unsigned integer +/// Struct Layout: [uint32_t x][uint32_t y] typedef uint32_t uvec2 __attribute__((ext_vector_type(2), aligned(4))); + + +/// uvec3 +/// 3D integer vector +/// Components are 32 bit fixed-size unsigned integer +/// Struct Layout: [uint32_t x][uint32_t y][uint32_t z][uint32_t __unused] typedef uint32_t uvec3 __attribute__((ext_vector_type(3), aligned(16))); + + +/// uvec4 +/// 4D integer vector +/// Components are 32 bit fixed-size unsigned integer +/// Struct Layout: [uint32_t x][uint32_t y][uint32_t z][uint32_t w] typedef uint32_t uvec4 __attribute__((ext_vector_type(4), aligned(16))); #else /// vec2 @@ -153,6 +203,7 @@ typedef struct VECTORMATH_ALIGNAS(vec2, 4) float y; } vec2; + /// vec3 /// 3D floating-point vector /// Components are 32 bit fixed-size floating-point number @@ -180,6 +231,7 @@ typedef union VECTORMATH_VECTORTYPE(vec3, 16) float data[4]; } vec3; + /// vec4 /// 4D floating-point vector /// Components are 32 bit fixed-size floating-point number @@ -222,6 +274,7 @@ typedef union VECTORMATH_VECTORTYPE(vec4, 16) //float data[4]; } vec4; + /// ivec2 /// 2D integer vector /// Components are 32 bit fixed-size signed integer @@ -231,6 +284,7 @@ typedef struct VECTORMATH_ALIGNAS(ivec2, 4) int32_t x, y; } ivec2; + /// ivec3 /// 3D integer vector /// Components are 32 bit fixed-size signed integer @@ -247,6 +301,7 @@ typedef union VECTORMATH_VECTORTYPE(ivec3, 16) int32_t data[4]; } ivec3; + /// ivec4 /// 4D integer vector /// Components are 32 bit fixed-size signed integer @@ -263,6 +318,7 @@ typedef union VECTORMATH_VECTORTYPE(ivec4, 16) int32_t data[4]; } ivec4; + /// ivec2 /// 2D integer vector /// Components are 32 bit fixed-size unsigned integer @@ -272,6 +328,7 @@ typedef struct VECTORMATH_ALIGNAS(uvec2, 4) uint32_t x, y; } uvec2; + /// ivec3 /// 3D integer vector /// Components are 32 bit fixed-size unsigned integer @@ -288,6 +345,7 @@ typedef union VECTORMATH_VECTORTYPE(uvec3, 16) uint32_t data[4]; } uvec3; + /// ivec4 /// 4D integer vector /// Components are 32 bit fixed-size unsigned integer @@ -305,6 +363,7 @@ typedef union VECTORMATH_VECTORTYPE(uvec4, 16) } uvec4; #endif // VECTORMATH_USE_CLANG_EXT + /// mat2 /// 2x2 floating-point row-major matrix /// Components are 32 bit fixed-size floating-point number @@ -330,6 +389,7 @@ typedef union VECTORMATH_VECTORTYPE(mat2, 16) float data[4]; } mat2; + /// mat3 /// 3x3 floating-point row-major matrix /// Components are 32 bit fixed-size floating-point number @@ -354,6 +414,7 @@ typedef union VECTORMATH_VECTORTYPE(mat3, 16) }; } mat3; + /// mat4 /// 4x4 floating-point row-major matrix /// Components are 32 bit fixed-size floating-point number