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)longvectors and matrices. These data types come with specialized overloads for all functions in Unity.Mathematics. Additionally, specializedRandom8/16/32/64/128types 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, andfloat8. 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-bitquadrupleprecision floats (scalar only), and 8-bitquarterprecision 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 optionalPromiseenum parameter available in many functions. - Easy To Use: MaxMath is just as easy to use as Unity.Mathematics. It supports features like
implicitandexplicittype 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
DEBUGonly runtime checks where appropriate, together ensuring it is production ready.
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.
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:
Arithmetic
Miscellaneous
addsub(a, b))- alternating add/subtractsubadd(a, b))- alternating subtract/addavg([integer type] a, [integer type] b))- rounded averageavg([floating point type] a, [floating point type] b))divrem(a, b, out remainder))square(a))mad(a, b, c))- multiply-addmsub(a, b, c))- multiply-subtractmaddsub(a, b, c))- alternating multiply-add/subtractmsubadd(a, b, c))- alternating multiply-add/subtractFloating 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 overflowpow(a, [floating point type] b)pow(a, [integer type] b)- optimized for integer exponentsexp(a)exp2([floating point type] a)exp2([integer type] a)- optimized for integer argumentsexp10(a)log(a)log2(a)log10(a)log(a, b)- logarithm with arbitrary basefrac(a)- fractional partmodf(a, out i)- split into fractional and integer partsrcp(a)fastrcp(a)- fast-approximate rcp(a)fmod(a, b)- a % bround(a)trunc(a)floor(a)ceil(a)div(a, b, [bool] fast)- (fast-approximate) divisiondad(a, b, c, [bool] fast)- fast-approximate) divide-adddsub(a, b, c, [bool] fast)- fast-approximate) divide-subtractdaddsub(a, b, c, [bool] fast)- fast-approximate) alternating divide-add/subtractdsubadd(a, b, c, [bool] fast)- fast-approximate) alternating divide-add/subtractInteger
mulwide(a, b, out lo, out hi)- full precision multiplicationisdivisible(a, b)- a % b == 0intsqrt(a)intcbrt(a)inthypot(a, b)- intsqrt(a² + b²) without overflowintpow(a, b)floorpow2(a)- round to nearest smaller power of 2ceilpow2(a)- round to nearest greater power of 2intlog10(a)intlog2(a)floorlog2(a)- intlog2(floorpow2(a))ceillog2(a)- intlog2(ceilpow2(a))factorial(a)gcd(a, b)- greatest common divisorlcm(a, b)- least common multiplecomb(a, b)- binomial coefficientperm(a, b)- number of k-permutations of n / ordered selections without repetition and with orderSaturation 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 sumcprodsaturated(a, b)- column productto[any type]saturated([any type] a)- cast the input to the return type, saturated to Min/MaxValue in case of overflowSequences
nextgreater(a)- next greater representable value, primarily intended for floating point valuesnextsmaller(a)- next smaller representable value, primarily intended for floating point valuesnexttoward(a, b)- next representable value from a towards broundmultiple(a, b)- among all multiples of b, returns the nearest one to afloormultiple(a, b)- among all multiples of b, returns the nearest smaller one to atruncmultiple(a, b)- among all multiples of b, returns the nearest greater one to atruncmultiple(a, b)- among all multiples of b, returns the nearest one to a towards 0Sign Manipulation
abs(a)nabs(a)- -abs(a)chgsign(a, b)- b < 0 ? -a : acopysign(a, b)- copy the sign of b to asign(a)- if (a == 0) return 0; else return a < 0 ? -1 : 1;Vector Reduction
csum(a)- sum of all vector elementscprod(a)- product of all vector elementscavg([integer type] a)- the ceiling of the average of all vector elementscavg([floating point type] a)- the true average of all vector elementsdot(a, b)sad(a, b)- Sum of Absolute Differences of corresponding vector components
Bitwise
Bitfields
bitfield(params a)- pack multiple values into one larger integerbitfield[numBits](a, b)- create a bitfield of `a` consecutive 1-bits starting at bit index bbitmask(a)- create a bitfield from a boolean vectorbits_extract(a, b, c)- extract c number of bits from a starting at index blzmask(a)- create a mask from leading zeros of al1mask(a)- create a mask from leading ones of atzmask(a)- create a mask from trailing zeros of at1mask(a)- create a mask from trailing ones of abits_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 bitsbits_depositparallel(a, b)- inverse of bits_extractparallel; scatter contiguous low-order bits from a into the positions selected by the bitmask btobool[bits](a)- boolean vector from a bitmasksignextend(a, b)- treat a as an integer with b bits and sign-extend itTesting Bits
testbit(a, b)- test whether bit b of a is settestbitset(ref a, b)- test whether bit b of a is set and set it to 1 afterwardstestbitreset(ref a, b)- test whether bit b of a is set and set it to 0 afterwardstestbitflip(ref a, b)- test whether bit b of a is set and set it to its opposite afterwardsBoolean Operations
andnot(a, b)- a & ~bbits_select(a, b, c)- per-bit conditional selectCounting Bits
countbits(a)- count bits set to 1countzerobits(a)- count bits set to 0lzcnt(a)- count leading bits set to 0l1cnt(a)- count leading bits set to 1tzcnt(a)- count trailing bits set to 0t1cnt(a)- count trailing bits set to 1parityeven(a)- test whether the number of set bits in a is evenparityodd(a)- test whether the number of set bits in a is oddBitwise Transformations
shl/shrl/shra(a, [vector integer type] b)- per-element logical/arithmetic bit shift left/right of vector typesrol/ror(a, [scalar integer type] b)- uniform bitwise rotate left/rightrol/ror([vector integer type] a, [vector integer type] b)- bitwise per-element rotate left/rightreversebits(a)reversebytes(a)bits_zerohigh(a, b)- set all bits in a to 0 starting at index blzfill(a)- set leading zeros to 1tzfill(a)- set trailing zeros to 1l1clear(a)- set leading ones to 0t1clear(a)- set trailing ones to 0bits_extractlowest(a)- extract only the lowest 1-bit as a 1-bitbits_extractlowest0(a)- extract only the lowest 0-bit as a 1-bitbits_setlowest(a)- set the lowest 0-bit to 1bits_resetlowest(a)- set the lowest 1-bit to 0bits_surroundlowest(a)- set the lowest 1-bit to 0 and all other bits to 1bits_surroundlowest0(a)- set the lowest 0-bit to 0 and all other bits to 1Vector Reduction
cand(a)- bitwise AND between all vector elementscor(a)- bitwise OR between all vector elementscxor(a)- bitwise XOR between all vector elements
Comparison
Miscellaneous
approx([floating point type] a, [floating point type] b)- test for approximate equalitycompareto(a, b)- a == b => 0; a < b => -1, a > b => 1 (IComparable.CompareTo)step(a, b)- a >= b ? 1 : 0ispow2(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 parametersminmag(a)- minimum value with regards to absolute magnitudemaxmag(a)- maximum value with regards to absolute magnitudeminmaxmag(a, out b, out c)- minimum and maximum value with regards to absolute magnitude as out parametersclamp(a, b, c)saturate(a)- clamp within [0, 1]select(a, b, [boolean type] c)- select between a and b based on cselect(a, b, [scalar integer] c)- select between a and b based on bitmask cnegateif(a, [boolean type] c)- negate a if c is trueVector Evaluation
all([numeric type] a)- test whether all values are non-zeroall([boolean type] a)- test whether all values are trueany([numeric type] a)- test whether any value is non-zeroany([boolean type] a)- test whether any value is trueall_dif(a, b)- test whether a and b do not share any components with each otherall_dif(a)- test whether all values in a are uniqueall_eq(a)- test whether all values are the same within a vectorcount([boolean type] a)- number of true valuesfirst([boolean type] a)- index of the first true valuelast([boolean type] a)- index of the last true valueVector Reduction
cmin(a)- minimum value in a vectorcmax(a)- maximum value in a vectorcminmax(a, out b, out c)- minimum and maximum values in a vector as out parameterscminmag(a)- minimum value with regards to absolute magnitude in a vectorcmaxmag(a)- maximum value with regards to absolute magnitude in a vectorcminmaxmag(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 radiansangledelta(a, b)- smallest difference of two angles in unsigned radiansangledeltasgn(a, b)- smallest difference of two angles in signed radiansangledeltadeg(a, b)- smallest difference of two angles in unsigned degreesangledeltasgndeg(a, b)- smallest difference of two angles in signed degreescross(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 directionorthonormal_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 brepeat(a, b)- loop between 0 and bsmoothlerp(a, b, c)- cubic interpolationsmoothstep(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 vectorsrotate(a, b)- rotate a vector by a rotation matrixmulScale(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 onesreverse(a)shuffle(a, [integer vector] b)- shuffle a vector based on indices stored in order in bshuffle(a, b, params [ShuffleComponent] c)- shuffle two vectors together, selecting elements with ShuffleComponent arguments in ordervshl/vshr(a, [integer vector] b)- similar to logical bitshifting where one bit corresponds to one vector elementvrol/vror(a, [integer vector] b)- similar to bitwise rotation where one bit corresponds to one vector element
Special Functions
gamma(a)erf(a)- error functionerfc(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 noisenoise.pnoise(a)- periodic perlin noisenoise.snoise(a)- simplex noisenoise.psrdnoise(a)- periodic simplex noise with fixed gradients and analytical derivativenoise.psrnoise(a)- periodic simplex noise with rotating gradients, but without the analytical derivativenoise.srdnoise(a)- non-periodic simplex noise with rotating gradients and analytical derivativenoise.srnoise(a)- non-periodic simplex noise with fixed gradients, without the analytical derivative
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.
- 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 namedmask[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 arepublicand 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.
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.Math → MaxMath.math
and
MaxMath.Geometry → MaxMath
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.
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:
- Name: MrUnbelievable
- URL: https://registry.npmjs.org
- Scopes: com.mrunbelievable
- Click Save.
- Open Window → Package Manager.
- In the package list, select My Registries.
- Install MaxMath from the 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.
If this repository has been valuable to your projects and you'd like to support my work, consider making a donation.






















