Skip to content

MrUnbelievable92/MaxMath

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

180 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MaxMath

MaxMath is the most powerful and extensive SIMD math library available to Unity developers. Built on top of Unity.Mathematics and utilizing Unity.Burst, it introduces the following key features:

  • Support For All Primitive Data Types: MaxMath adds support for (s)byte, (u)short, and (u)long vectors and matrices. These data types come with specialized overloads for all functions in Unity.Mathematics. Additionally, specialized Random8/16/32/64/128 types are available for efficient pseudo-random number generation.
  • Wider Vectors With Full Hardware Support: Vector types are expanded to 256 bits, enabling types like byte32, short16, int8, and float8. This allows you to leverage the full potential of SIMD computation.
  • Many Additional Functions: MaxMath includes a massive library of mathematical functions not found in Unity.Mathematics, with about five times as many highly optimized functions at your disposal. Each function is fully documented with XML annotations. A full list is provided further below.
  • Exotic Data Types: MaxMath introduces data types such as (U)Int128 (scalar only), 128-bit quadruple precision floats (scalar only), and 8-bit quarter precision floats (in both scalar and vector forms). Additionally, Divider<T> offers highly optimized integer division operations, extending and outperforming specialized libraries like libdivide.
  • Written Entirely With Hardware Intrinsics: MaxMath guarantees optimal performance by utilizing specialized CPU instructions for both ARM and x86 ISAs, while abstracting these complexities away from the user entirely.
  • Extends The Burst Compiler: MaxMath integrates deeply with Unity.Burst and LLVM, leveraging Unity.Burst.CompilerServices.Constant.IsConstantExpression<T>() to include code typically only found in optimizing compilers. This functionality allows MaxMath to choose more optimized code paths at compile time, and users can influence this behavior via the optional Promise enum parameter available in many functions.
  • Easy To Use: MaxMath is just as easy to use as Unity.Mathematics. It supports features like implicit and explicit type conversions, making it seamless for you to use if you expect typical C# behavior of primitive types.
  • Extensive Test Coverage: MaxMath is backed by 250,000 lines of unit tests for its 750,000 lines of code, as well as DEBUG only runtime checks where appropriate, together ensuring it is production ready.

Why MaxMath over Unity.Mathematics?

Prior to version 3.0, MaxMath served as a supplementary library to Unity.Mathematics. Starting with 3.0, it is a drop-in replacement/wrapper for Unity.Mathematics, fully compatible while extending it with additional MaxMath functionality.

MaxMath builds on Unity.Mathematics with additional functionality and numerous performance improvements (See the 3.0 patch notes for the changes). Several bugs in Unity.Mathematics have not been fixed for multiple years, particularly with regards to half.

MaxMath is actively maintained, with recent releases and public GitHub Issues/Discussions for feedback. By comparison, Unity.Mathematics still shows a substantial amount of open issues and feature requests in its public repository, and its README notes that pull requests are not accepted.

Types

Integer

alt text

alt text

alt text

alt text

alt text

alt text

alt text

alt text

alt text

alt text

Floating Point

alt text

alt text

alt text

alt text

alt text

Geometry

alt text

Miscellaneous

alt text

alt text

alt text

Functions

Note: The function signatures (but not their names), parameter names, and descriptions shown below have been intentionally simplified to keep this catalog concise and easy to browse. They do not reflect the naming conventions or XML documentation used throughout MaxMath, which provide substantially more descriptive parameter names, detailed explanations, and full IntelliSense support in IDEs (see the example below).

This section is intended solely as a high-level overview of the available functionality rather than a replacement for the library's built-in documentation.

In addition, many functions have an optional enum Promise parameter for optimized code paths not listed here.

Each operation is available for all applicable scalar, vector, and matrix types.

An example for XML documentation used in MaxMath: alt text

Arithmetic
Miscellaneous
  • addsub(a, b)) - alternating add/subtract
  • subadd(a, b)) - alternating subtract/add
  • avg([integer type] a, [integer type] b)) - rounded average
  • avg([floating point type] a, [floating point type] b))
  • divrem(a, b, out remainder))
  • square(a))
  • mad(a, b, c)) - multiply-add
  • msub(a, b, c)) - multiply-subtract
  • maddsub(a, b, c)) - alternating multiply-add/subtract
  • msubadd(a, b, c)) - alternating multiply-add/subtract
Floating Point
  • sqrt(a)
  • rsqrt(a) - 1 / sqrt(a)
  • fastrsqrt(a) - fast-approximate rsqrt(a)
  • cbrt(a)
  • rcbrt(a) - 1 / cbrt(a)
  • hypot(a, b) - sqrt(a² + b²) without overflow
  • pow(a, [floating point type] b)
  • pow(a, [integer type] b) - optimized for integer exponents
  • exp(a)
  • exp2([floating point type] a)
  • exp2([integer type] a) - optimized for integer arguments
  • exp10(a)
  • log(a)
  • log2(a)
  • log10(a)
  • log(a, b) - logarithm with arbitrary base
  • frac(a) - fractional part
  • modf(a, out i) - split into fractional and integer parts
  • rcp(a)
  • fastrcp(a) - fast-approximate rcp(a)
  • fmod(a, b) - a % b
  • round(a)
  • trunc(a)
  • floor(a)
  • ceil(a)
  • div(a, b, [bool] fast) - (fast-approximate) division
  • dad(a, b, c, [bool] fast) - fast-approximate) divide-add
  • dsub(a, b, c, [bool] fast) - fast-approximate) divide-subtract
  • daddsub(a, b, c, [bool] fast) - fast-approximate) alternating divide-add/subtract
  • dsubadd(a, b, c, [bool] fast) - fast-approximate) alternating divide-add/subtract
Integer
  • mulwide(a, b, out lo, out hi) - full precision multiplication
  • isdivisible(a, b) - a % b == 0
  • intsqrt(a)
  • intcbrt(a)
  • inthypot(a, b) - intsqrt(a² + b²) without overflow
  • intpow(a, b)
  • floorpow2(a) - round to nearest smaller power of 2
  • ceilpow2(a) - round to nearest greater power of 2
  • intlog10(a)
  • intlog2(a)
  • floorlog2(a) - intlog2(floorpow2(a))
  • ceillog2(a) - intlog2(ceilpow2(a))
  • factorial(a)
  • gcd(a, b) - greatest common divisor
  • lcm(a, b) - least common multiple
  • comb(a, b) - binomial coefficient
  • perm(a, b) - number of k-permutations of n / ordered selections without repetition and with order
Saturation Arithmetic (returns type.MinValue/MaxValue in case of overflow)
  • addsaturated(a, b)
  • subsaturated(a, b)
  • mulsaturated(a, b)
  • divsaturated(a, b)
  • csumsaturated(a, b) - column sum
  • cprodsaturated(a, b) - column product
  • to[any type]saturated([any type] a) - cast the input to the return type, saturated to Min/MaxValue in case of overflow
Sequences
  • nextgreater(a) - next greater representable value, primarily intended for floating point values
  • nextsmaller(a) - next smaller representable value, primarily intended for floating point values
  • nexttoward(a, b) - next representable value from a towards b
  • roundmultiple(a, b) - among all multiples of b, returns the nearest one to a
  • floormultiple(a, b) - among all multiples of b, returns the nearest smaller one to a
  • truncmultiple(a, b) - among all multiples of b, returns the nearest greater one to a
  • truncmultiple(a, b) - among all multiples of b, returns the nearest one to a towards 0
Sign Manipulation
  • abs(a)
  • nabs(a) - -abs(a)
  • chgsign(a, b) - b < 0 ? -a : a
  • copysign(a, b) - copy the sign of b to a
  • sign(a) - if (a == 0) return 0; else return a < 0 ? -1 : 1;
Vector Reduction
  • csum(a) - sum of all vector elements
  • cprod(a) - product of all vector elements
  • cavg([integer type] a) - the ceiling of the average of all vector elements
  • cavg([floating point type] a) - the true average of all vector elements
  • dot(a, b)
  • sad(a, b) - Sum of Absolute Differences of corresponding vector components
Bitwise
Bitfields
  • bitfield(params a) - pack multiple values into one larger integer
  • bitfield[numBits](a, b) - create a bitfield of `a` consecutive 1-bits starting at bit index b
  • bitmask(a) - create a bitfield from a boolean vector
  • bits_extract(a, b, c) - extract c number of bits from a starting at index b
  • lzmask(a) - create a mask from leading zeros of a
  • l1mask(a) - create a mask from leading ones of a
  • tzmask(a) - create a mask from trailing zeros of a
  • t1mask(a) - create a mask from trailing ones of a
  • bits_masktolowest(a) - mask up to lowest 1-bit (inclusive)
  • bits_masktolowest0(a) - mask up to lowest 0-bit (inclusive)
  • bits_maskfromlowest(a) - mask from lowest 1-bit (inclusive)
  • bits_maskfromlowest0(a) - mask from lowest 0-bit (inclusive)
  • bits_extractparallel(a, b) - pack the bits from a selected by the bitmask b into contiguous low-order bits
  • bits_depositparallel(a, b) - inverse of bits_extractparallel; scatter contiguous low-order bits from a into the positions selected by the bitmask b
  • tobool[bits](a) - boolean vector from a bitmask
  • signextend(a, b) - treat a as an integer with b bits and sign-extend it
Testing Bits
  • testbit(a, b) - test whether bit b of a is set
  • testbitset(ref a, b) - test whether bit b of a is set and set it to 1 afterwards
  • testbitreset(ref a, b) - test whether bit b of a is set and set it to 0 afterwards
  • testbitflip(ref a, b) - test whether bit b of a is set and set it to its opposite afterwards
Boolean Operations
  • andnot(a, b) - a & ~b
  • bits_select(a, b, c) - per-bit conditional select
Counting Bits
  • countbits(a) - count bits set to 1
  • countzerobits(a) - count bits set to 0
  • lzcnt(a) - count leading bits set to 0
  • l1cnt(a) - count leading bits set to 1
  • tzcnt(a) - count trailing bits set to 0
  • t1cnt(a) - count trailing bits set to 1
  • parityeven(a) - test whether the number of set bits in a is even
  • parityodd(a) - test whether the number of set bits in a is odd
Bitwise Transformations
  • shl/shrl/shra(a, [vector integer type] b) - per-element logical/arithmetic bit shift left/right of vector types
  • rol/ror(a, [scalar integer type] b) - uniform bitwise rotate left/right
  • rol/ror([vector integer type] a, [vector integer type] b) - bitwise per-element rotate left/right
  • reversebits(a)
  • reversebytes(a)
  • bits_zerohigh(a, b) - set all bits in a to 0 starting at index b
  • lzfill(a) - set leading zeros to 1
  • tzfill(a) - set trailing zeros to 1
  • l1clear(a) - set leading ones to 0
  • t1clear(a) - set trailing ones to 0
  • bits_extractlowest(a) - extract only the lowest 1-bit as a 1-bit
  • bits_extractlowest0(a) - extract only the lowest 0-bit as a 1-bit
  • bits_setlowest(a) - set the lowest 0-bit to 1
  • bits_resetlowest(a) - set the lowest 1-bit to 0
  • bits_surroundlowest(a) - set the lowest 1-bit to 0 and all other bits to 1
  • bits_surroundlowest0(a) - set the lowest 0-bit to 0 and all other bits to 1
Vector Reduction
  • cand(a) - bitwise AND between all vector elements
  • cor(a) - bitwise OR between all vector elements
  • cxor(a) - bitwise XOR between all vector elements
Comparison
Miscellaneous
  • approx([floating point type] a, [floating point type] b) - test for approximate equality
  • compareto(a, b) - a == b => 0; a < b => -1, a > b => 1 (IComparable.CompareTo)
  • step(a, b) - a >= b ? 1 : 0
  • ispow2(a)
  • isnan(a)
  • isinf(a)
  • isfinite(a)
  • isnormal(a)
  • issubnormal(a)
  • indexof([vector type] a, [scalar type] b)
  • isinrange(a, b, c) - test whether a lies in [b, c]
Selection
  • min(a)
  • max(a)
  • minmax(a, out b, out c) - minimum and maximum value as out parameters
  • minmag(a) - minimum value with regards to absolute magnitude
  • maxmag(a) - maximum value with regards to absolute magnitude
  • minmaxmag(a, out b, out c) - minimum and maximum value with regards to absolute magnitude as out parameters
  • clamp(a, b, c)
  • saturate(a) - clamp within [0, 1]
  • select(a, b, [boolean type] c) - select between a and b based on c
  • select(a, b, [scalar integer] c) - select between a and b based on bitmask c
  • negateif(a, [boolean type] c) - negate a if c is true
Vector Evaluation
  • all([numeric type] a) - test whether all values are non-zero
  • all([boolean type] a) - test whether all values are true
  • any([numeric type] a) - test whether any value is non-zero
  • any([boolean type] a) - test whether any value is true
  • all_dif(a, b) - test whether a and b do not share any components with each other
  • all_dif(a) - test whether all values in a are unique
  • all_eq(a) - test whether all values are the same within a vector
  • count([boolean type] a) - number of true values
  • first([boolean type] a) - index of the first true value
  • last([boolean type] a) - index of the last true value
Vector Reduction
  • cmin(a) - minimum value in a vector
  • cmax(a) - maximum value in a vector
  • cminmax(a, out b, out c) - minimum and maximum values in a vector as out parameters
  • cminmag(a) - minimum value with regards to absolute magnitude in a vector
  • cmaxmag(a) - maximum value with regards to absolute magnitude in a vector
  • cminmaxmag(a, out b, out c) - minimum and maximum values with regards to absolute magnitude in a vector as out parameters
Geometry
Miscellaneous
  • transform(a, MinMaxAABB aabb)
  • angle(a, b) - unsigned angle between a and b in radians
  • angledelta(a, b) - smallest difference of two angles in unsigned radians
  • angledeltasgn(a, b) - smallest difference of two angles in signed radians
  • angledeltadeg(a, b) - smallest difference of two angles in unsigned degrees
  • angledeltasgndeg(a, b) - smallest difference of two angles in signed degrees
  • cross(a, b)
  • project(a)
  • projectsafe(a)
  • normalize(a)
  • normalizesafe(a)
  • length(a)
  • lengthsq(a)
  • distance(a, b)
  • distancesq(a, b)
  • reflect(a, b)
  • refract(a, b, c)
  • faceforward(a, b, c) - flips a vector if the two other vectors are pointing in the same direction
  • orthonormal_basis(a, out b, out c)
  • orthonormalize(a)
Trigonometry
  • radians(a)
  • degrees(a)
  • sin(a)
  • cos(a)
  • sincos(a, out b, out c)
  • tan(a)
  • asin(a)
  • acos(a)
  • atan(a)
  • atan2(a, b)
  • sinh(a)
  • cosh(a)
  • tanh(a)
  • asinh(a)
  • acosh(a)
  • atanh(a)
RigidTransform
  • inverse(a)
  • mul(a, b)
  • rotate(a, b)
  • transform(a, b)
AffineTransform
  • decompose(a, out b, out c, out d)
  • inverse(a)
  • mul(a, b)
  • rotate(a, b)
  • transform(a, b)
Quaternion
  • conjugate(a)
  • inverse(a)
  • dot(a, b)
  • length(a)
  • lengthsq(a)
  • normalize(a)
  • normalizesafe(a)
  • exp(a)
  • unitexp(a)
  • log(a)
  • unitlog(a)
  • mul(a, b)
  • rotate(a, b)
  • slerp(a, b, c)
  • nlerp(a, b, c)
  • angle(a, b)
  • Euler(a, b)
  • EulerXYZ(a)
  • EulerXZY(a)
  • EulerYXZ(a)
  • EulerYZX(a)
  • EulerZXY(a)
  • EulerZYX(a)
Interpolation
  • lerp(a, b, c)
  • unlerp(a, b, c)
  • remap(a, b, c, d, e)
  • pingpong(a, b) - back and forth between 0 and b
  • repeat(a, b) - loop between 0 and b
  • smoothlerp(a, b, c) - cubic interpolation
  • smoothstep(a, b, c) - hermite interpolation
Matrix Operations
  • determinant(a)
  • inverse(a)
  • fastinverse(a)
  • pseudoinverse(a)
  • transpose(a)
  • transform(a, b)
  • mul(a, b) - all possible matrix multiplication operations between matrices and vectors
  • rotate(a, b) - rotate a vector by a rotation matrix
  • mulScale(a, b)
  • scaleMul(a, b)
  • svdInverse(a) - singular value decomposition (svd)
  • svdRotation(a) - singular value decomposition (svd)
Vector Shuffling
  • compress([pointer] a, b, c, [boolean type] d) - filter out disabled components and left-pack the remaining ones
  • reverse(a)
  • shuffle(a, [integer vector] b) - shuffle a vector based on indices stored in order in b
  • shuffle(a, b, params [ShuffleComponent] c) - shuffle two vectors together, selecting elements with ShuffleComponent arguments in order
  • vshl/vshr(a, [integer vector] b) - similar to logical bitshifting where one bit corresponds to one vector element
  • vrol/vror(a, [integer vector] b) - similar to bitwise rotation where one bit corresponds to one vector element
Special Functions
  • gamma(a)
  • erf(a) - error function
  • erfc(a) - complementary error function
Type Conversion
  • roundto[integer type]([floating point type] a)
  • truncto[integer type]([floating point type] a)
  • floorto[integer type]([floating point type] a)
  • ceilto[integer type]([floating point type] a)
  • to[numeric type]([boolean type] a) - 0 or 1 based on the boolean argument (unsafe)
  • to[numeric type]safe([boolean type] a) - 0 or 1 based on the boolean argument (safe)
  • to[boolean type]([numeric type] a) - true or false based on whether the argument is 0 or 1 (unsafe)
  • to[boolean type]safe([numeric type] a) - true or false based on whether the argument is 0 or not (safe)
  • to[floating point type]unsafe([integer type] a) - unsafe, fast conversion of integer to floating point types based on optional `enum Promise` argument
Noise
  • noise.cellular(a)
  • noise.cellular2x2(a)
  • noise.cellular2x2x2(a)
  • noise.cnoise(a) - perlin noise
  • noise.pnoise(a) - periodic perlin noise
  • noise.snoise(a) - simplex noise
  • noise.psrdnoise(a) - periodic simplex noise with fixed gradients and analytical derivative
  • noise.psrnoise(a) - periodic simplex noise with rotating gradients, but without the analytical derivative
  • noise.srdnoise(a) - non-periodic simplex noise with rotating gradients and analytical derivative
  • noise.srnoise(a) - non-periodic simplex noise with fixed gradients, without the analytical derivative

What Kind Of Performance To Expect

alt text

MaxMath was designed with performance as a primary objective from the very beginning. While it started as an extension of Unity.Mathematics to cover every C# primitive type - including integer vectors, matrices, and numerous additional mathematical functions - it has since evolved into a complete rewrite and replacement of it.

The 1.x development cycle focused on vectorizing virtually every operation and mathematical function. The 2.x cycle introduced architecture-specific implementations with optimized instruction selection and fallbacks across multiple SIMD instruction sets, initially targeting x86 (AVX2 → AVX → SSE4 → SSE2) before expanding to ARM NEON. The current 3.x cycle removes fundamental limitations inherited from Unity.Mathematics, such as inefficient boolean vector representations (and non-vectorized or poorly-vectorized algorithms), by introducing native SIMD masks internally while preserving a familiar boolean vector API.

Performance work has been an ongoing effort throughout every release. Nearly every function and operator has undergone repeated optimization with an emphasis on minimizing latency, reducing instruction count and code size, and generating predictable machine code. Whenever practical, implementations are written directly with SIMD intrinsics to retain precise control over the generated assembly and avoid compiler-dependent code generation.

Many operations employ state-of-the-art algorithms drawn from academic literature, while others are based on novel implementations developed specifically for MaxMath to achieve exceptionally efficient SIMD execution. Combined with extensive architecture-specific specialization and years of iterative optimization, the result is a library essentially generating hand-written machine code out-of-the-box while remaining entirely accessible through a high-level C# API.

Recommendations for Optimal Performance

  • It is recommended, just like with Unity.Mathematics, to use vector types that use up an entire SIMD register (128 and 256 bits, respectively). LLVM has a very hard time optimizing code which does not follow this recommendation
  • Wherever possible, it is adviced not to declare boolean vectors as temporary variables on the stack. MaxMath uses a 1:1 representation of SIMD masks for boolean data in the form of ref structs named mask[BITS]x[COLUMNS]x[ROWS]. They are implicitly convertible to and from boolean vectors and matrices and should therefore be invisible to the user and cannot leave the stack, so the expected behaviour from using the Unity.Mathematics and earlier MaxMath API is still guaranteed, yet converting to and from boolean types comes at a performance cost already present in both Unity.Mathematics (although rarer) and MaxMath. Since the mask types are public and have the exact same API as corresponding boolean types, you are free to use them instead, yet their obscurity through specialization opens up a larger surface area for programmer error.
  • One of the core strengths of MaxMath is that it provides operations whose implementations are better than what a compiler can synthesize from primitive operators; prefer using dedicated MaxMath operations over composing equivalent expressions manually. Many functions map to specialized SIMD instructions or architecture-specific implementations that cannot be recognized reliably by Burst or LLVM. If you are able to exploit specialized SIMD instructions for mathematical algorithms, consider submitting the resulting code to MaxMath as a pull-request. Otherwise you are very much welcome to open a feature request via the issue tracker.

Migrating from Unity.Mathematics

⚠️ Back up your project before migrating.

Although the migration is usually straightforward, some serialized values, especially vector fields in the Inspector, may need to be rechecked afterwards.

For most projects, a simple find-and-replace is enough: replace Unity.Mathematics with MaxMath.

Sub-namespaces were merged into MaxMath directly. After replacing Unity.Mathematics with MaxMath, replace:

MaxMath.Geometry.MathMaxMath.math and MaxMath.GeometryMaxMath

A number of types, members, and Unity.Mathematics.math functions have been marked as obsolete and may need small code adjustments during migration in order to avoid warnings and improve performance.

Vector fields are exposed as ref properties in MaxMath. This means you cannot take their address in an unsafe context, and you must initialize the vector before assigning to its components either directly or using the out keyword.

Because fields are no longer exposed directly, serialized Unity.Mathematics vector values shown in the Inspector may be invalidated during migration. MaxMath uses custom property serialization for these types.

For best performance, avoid declaring bool{X} vectors directly, such as bool3 cmp = myVec3a > myVec3b. MaxMath uses optimized mask types behind the scenes. That code still works (bool vectors exist in MaxMath and are not marked as obsolete, all mask types are implicitly convertible to and from bool vectors and matrices), and keeping it as-is does not hurt performance compared to Unity.Mathematics - this would simply be an additional, sometimes very relevant performance optimization.

If you encountered another required step during migration, please open an issue to report it.

How To Install This Library

It is highly encouraged to use the Scoped Registries feature for installing MaxMath.

Installing using Scoped Registries:

  • Open your Unity project.
  • Go to Edit → Project Settings → Package Manager.
  • Under Scoped Registries, click + to add a new registry.
  • Enter the registry details:
  • Click Save.
  • Open Window → Package Manager.
  • In the package list, select My Registries.
  • Install MaxMath from the registry.

Why use a scoped registry?

  • Easy updates – Receive new versions directly through Unity’s Package Manager without manual downloads.
  • Version management – Switch, lock, or roll back versions cleanly using Unity’s built-in tooling.
  • Cleaner projects – No need to store package files inside your repository or project folder.
  • Dependency resolution – Unity automatically handles dependencies and compatibility.
  • Team-friendly – Everyone on the project uses the same source and versions with minimal setup.
  • Faster setup – Install in a few clicks instead of manually importing or maintaining local packages.
  • No IDE clutter – The package source code does not appear in your IDE, keeping your workspace focused on your own project code.

Donations

If this repository has been valuable to your projects and you'd like to support my work, consider making a donation.

donateBTC donatePP

About

A successor to the SIMD math library Unity.Mathematics, extending it to all C# numeric types while adding many new types and functions. Written entirely with hardware intrinsics, using Unity.Burst.

Topics

Resources

License

Apache-2.0, Unknown licenses found

Licenses found

Apache-2.0
LICENSE
Unknown
LICENSE.meta

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages