Codes Otaku Math Module (60+ functions, 700+ lines)

I binged the whole day to release this ultimate math module for practical game development. It includes various functions to help ease your development.
I know that there is a lot of math modules out there, but most of those are focusing on including mythical constants and glorious mathematical functions that have little to no use in game development. So today am happy to release this module to the community as open source (MIT LICENCE) in github!
I’ll be happy to see your contributions, and even happier to include your fixes and new features!
There is still a lot to add, and functions that I have to document in the near future, I
l’ll update you when there is a new update!
This module is not yet tested fully, in fact I made the whole code in one sit character by character, I have no idea how I survived all that math and programming in one go :smiley_cat:

Imma complete documentation and create unit tests when I get some rest! otherwise I’ll be happy if you can help me improve this module :wink:

CodesOtakuModules/Math.lua at main · CodesOtakuYT/CodesOtakuModules (github.com)

{
	----> Constants
	PI = PI, -- Ratio of a circle's circumference to its diameter.
	TAU = TAU, -- PI*2
	E = E, -- Euler's number
	PHI = PHI, -- Golden Ratio

	----> Pure mathematical functions
	nrt = nrt, -- Nth root; (x, n)
	cbrt = cbrt, -- Cubic root; (x)
	inverse = inverse, -- 1/x; (x)
	ln = ln, -- Natural logarithm; (x)
	log2 = log2, -- Log of base 2
	cos = cos, -- cos(x)
	sin = sin, -- sin(x)
	ncos = ncos, -- -cos(x), it might seem silly, but I added this so I can optimize derivative and integral by referencing it, so you can pass in this function to integral, and it's already optimized
	nsin = nsin, -- -sin(x)
	sec = sec, -- Secant(x), I don't use this functions usually, but it might be helpful if you have a formula that use them and you're too lazy like me
	csc = csc, -- Co-secant(x),
	cot = cot, -- Co-tangent(x),
	versin = versin, -- versin(θ) = 1 - cos(θ) = 2sin²(θ/2)
	coversin = coversin, -- coversine(θ) = 1 - sin(θ)
	exsec = exsec, -- exsecant(θ) = sec(θ) - 1 = 1 / cos(θ) - 1
	haversin = haversin, -- haversine(θ) = sin²(0⁄2) = 1 - cos(θ) / 2
	ease = ease, -- https://godotengine.org/qa/59172/how-do-i-properly-use-the-ease-function
	smoothStep = smoothStep, -- https://thebookofshaders.com/glossary/?search=smoothstep
	factorial = factorial, -- x!
	fibonacci = fibonacci, -- fib(x-1)+fib(x-2)

	----> Practical mathematical functions
	numberLength = numberLength, -- returns the number of digits in the number #tostring(number)
	fract = fract, -- return the fractional part of a number, what's after the comma
	toFract = toFract, -- return the number after the comma like 0.number
	wrap = wrap, -- it cycles a arbitrary value between min and max, equivalent to the modulo operator but with configurable minimum
	step = step, -- returns the closest multiple of factor to x, can be used to snap a position's components to a grid (Minecraft...)
	snap = snap, -- the same as step, but can also handle seperation, Ex: your grid have a border
	stepDecimals = stepDecimals, -- round the number to n digits after the comma
	lerp = lerp, -- takes a range [a -> b] and a t value [0->1]. it returns a value travalling from a to b linearly, where t is the percentage it advanced (Ex: 50% = 0.5)
	invLerp = invLerp, inverseLerp = invLerp, -- takes a range [c -> d] and a value x, it returns the t value of the value in range, basically where the value is relative to the range.
	map = map, -- lerp(o1, o2, inverseLerp(i1, i2, x)), remaps a value x from the range [i1->i2] to [o1->o2], can be useful to create sliders.
	lerpExp = lerpExp, -- exponential lerp
	invLerpExp = invLerpExp, inverseLerpExp = invLerpExp, -- inverse exponential lerp
	
	----> Conversion
	cartesian2polar = cartesian2polar, -- x, y to rau, angle
	cylindrical2cartesian = cylindrical2cartesian, -- rau, angle, z to x,y,z
	spherical2cartesian = spherical2cartesian, -- rau, angle, theta to x,y,z
	polar2cartesian = polar2cartesian, -- rau, angle to x,y

	----> Comparaison functions
	approxEq = approxEq, -- Returns true if x approximately equals y, where EPSILON is the tolerance, error or deviation allowed; (x, y, epsilon?)
	approxZero = approxZero, -- Returns true if x approximately equals 0

	----> Calculus
	derivative = derivative, -- calculate the derivative of f using it's definite derivative (optimized) or numerically if none found
	integral = integral, -- calculate the integral of f from x1 to x2 using it's definite primitive (optimized) or numerically if none found
	integralAbs = integralAbs, -- the absolute version of the integral, the sign of f(x) is ignored
	addDefiniteFunction = addDefiniteFunction, -- takes 2 functions. a function and it's derivative, it will be used by the functions above if the definite version exist, as it's much better and accurate than the numerical method
	productDerivative = productDerivative, -- (f*g)' = f'g-g'f the chain rule
	quotientDerivative = quotientDerivative, -- (f/g)' = (f'g-g'f)/(g^2) the chain rule and the derivative of the inverse of f(x)
	compositeDerivative = compositeDerivative, -- (f(g))' = f'(g)*g'
	
	----> Table math
	sumT = sumT, -- Sum of the values; (table)
	differenceT = differenceT, -- Difference of the values; (table)
	productT = productT, -- Product of the values; (table)
	quotientT = quotientT, -- Quotient of the values; (table)
	meanT = meanT, -- Average of the values; (table)
	modeT = modeT, -- The middle value or the average of the middle values in the sorted version of the table; (table)
	maxT = maxT, -- The maximum value in the table, if isOverride is true, return the last maximum found, otherwise the first; (table, isOverride?)
	minT = minT, -- The minumum value in the table;, if isOverride is true, return the last minimum found, otherwise the first; (table, isOverride?)
	countValuesT = countValuesT, -- Returns a table with the count of all the values in the table; (table)
	rangeT = rangeT, -- Returns {min, minIndex}, {max, maxIndex}; (table)
	processPairsT = processPairsT, -- Gets a table with 2*n elements, it returns a table with n elements by processing each pair with the function f
	mapT = mapT, -- Gets a table [x1, x2, x3...xn] and a function, returns [f(x1), f(x2), f(x3)...f(xn)]
	filterT = filterT, -- Gets a table and a function, returns a new table with the elements that evaluated the function f(value, key) to true
	countT = countT, -- Accumulates the result of a function f(v, k) traversing a table, returns the accumulated value
	countMulT = countMulT, -- The same as countT but with multiplication
	sampleT = sampleT, -- Sample function output n times from x1 to x2 linearly
	
	----> Vector math
	distanceV = distanceV, -- Returns the distance between the position vec1 and vec2
	midPosV = midPosV, -- Returns the middle position between the position vec1 and vec2, equivalent to lerp(vec1, vec2, 0.5)
	applyV = applyV, -- Returns a new Vector3 by applying a function on the X, Y and Z components of a Vector3
	absV = absV, -- Returns a new Vector3 where all the components of the vector are absolute (positive or nil)
	
	-- Random
	randomItemT = randomItemT, -- Returns a random key, value in table
	random = random, -- returns a random number in range [a,b]
	randomN = randomN, -- returns a random integer in range [a,b]
	
	----> Helper functions
	copyT = copyT, -- Returns a copy of a table
	invertT = invertT, -- the keys becomes the values and vice versa, takes a table [y1 = x1, y2 = x2...yn = xn], returns [x1 = y1, x2 = y2...xn = yn]
	zipT = zipT, -- takes 2 tables and zip them together {{t1[1], t2[1]}, {t1[2], t2[2]}...{t1[n], t2[n]}}
	unzipT = unzipT, -- the inverse of zip, takes 1 table of pairs and unzip it into 2 tables
	valuesT = valuesT, -- return a table of all the values inside the table, there is also recursive mode for nested tables
	keysT = keysT, -- the same as valuesT, but for table keys
26 Likes

Not bad. Looks a bit more useful than the other math modules I’ve seen (looking at you, “SimpleBit”).

3 Likes

Hey! The Module was more for fun and is not intended for just maths. The maths was just an extra feature to experiment with.

And my Module is not based on maths, but instead more for Bit-proccessing.

4 Likes

Here is the most useful functions in my module currently in my opinion:

-- it will return how much digits in the number without string manipulation
-- Ex: 23443 -> 5
local function numberLength(x, base)

-- it will return the fractional term of a number
-- Ex: 234,5467 -> 0,5467
local function fract(x)

-- it will convert any number into a fraction
-- Ex: 235435 -> 0.235435
local function toFract(x, base)

-- it will cycle the value x between min and max, it's like using the modulo
-- or math.mod but with support to range [min, max]
-- Ex: when the mouse scroll, a value x get incremented indefinitely
-- And you want to select a item from your toolbar with that value
-- toolbar[wrap(x, 1, toolbarSlotsCount)]
local function wrap(x, min, max)

-- it will round the value x to nearest multiple of factor with the offset applied
-- it can be used to align a position's coordinates into a moving (offset) grid
local function step(x, factor, offset)

-- the same as step, but now your grid have a seperation gap (border maybe?) ;)
local function snap(x, factor, offset, sep)

-- it will return the value x with a specified number of digits after the comma
local function stepDecimals(x, decimalPlaces)
1 Like

Guess what, the comma in every number is also an operator : )
Here is how you can do it

local Math = require(MyModulePath)

local function comma(left, right)
	return left + Math.toFract(right)
end

print(comma(123, 8945)) --> 123.8945
print(comma(46, 103)) --> 46.103
print(comma(46, 102)) --> 46.102

In fact I got the idea of the function toFract when I was making a mathematical expression parser, where comma was also an actual operator lmao

1 Like

I might be wrong. But simply this.

function comma(y,z)
return tonumber(y.."."..z)
end

print(comma(8,5)) -- 8.5

The function still cool

1 Like

I wanted to do it the hardcore way, purely mathematical instead of string manipulation lmao
But that’s the smart way xD

1 Like

lol, I really like your way cuz I like maths now

1 Like

All of the functions are written by me and I totally understand most of them, yet I still get a low grade in mathematics, yikes :slight_smile:

2 Likes

wait I wanna compare the speed between my function and yours, but I can’t hop in studio rn so could you test it?

function geocomma(y,z)
return tonumber(y.."."..z)
end

function codesotakucomma(left,right)
return left + Math.toFract(right)
end

local timeforgeocomma = os.time()
print(geocomma(6,8))
print("geocomma:"..os.time() - timeforgeocomma)
local timeforotakucomma = os.time()
print(codesotakucomma(6,8))
print("codes otaku comma:"..os.time() - timeforotakucomma)
1 Like

that’s a big yike lol, I hope u get good grades

1 Like

1 Like

ahh you’ve beated my comma function, like bro I still don’t get why you get bad grades at math

1 Like

because computers are really good at numbers

local function toFract(x)
	return x*pow(10, -ceil(log(x, 10)))
end
1 Like

Sheeeesh, This is some BUSSIN’ mathematical work right here! Thank you for sharing this and I’m sure I’ll find a perfect use for this! :star_struck:

1 Like

That’s my pleasure Merokieo, glad you liked it!

This seems really good and to learn off aswell

1 Like

Yep once it’s fully documented. it’s even better as a learning material for sure, as I included functions that I actually use or thought that it might prove useful to future me or anyone else!

Assuming these functions stand for nthroot and cube root respectively there it should not be negative in the exponent. The results with this code produce the reciprocal of the expected results.

image

1 Like

Oh right, I guess I was drunk when I made that, I’ll fix it, thanks man!

1 Like