silverbullet/common/space_lua/stdlib/math.ts

103 lines
3.4 KiB
TypeScript

import {
LuaBuiltinFunction,
LuaRuntimeError,
LuaTable,
} from "$common/space_lua/runtime.ts";
export const mathApi = new LuaTable({
// Random number generation
random: new LuaBuiltinFunction((_sf, m?: number, n?: number) => {
if (m === undefined && n === undefined) {
// random() returns [0,1)
return Math.random();
} else if (n === undefined) {
// random(m) returns [1,m]
return Math.floor(Math.random() * m!) + 1;
} else {
// random(m,n) returns [m,n]
return Math.floor(Math.random() * (n - m! + 1)) + m!;
}
}),
// Basic functions
abs: new LuaBuiltinFunction((_sf, x: number) => Math.abs(x)),
ceil: new LuaBuiltinFunction((_sf, x: number) => Math.ceil(x)),
floor: new LuaBuiltinFunction((_sf, x: number) => Math.floor(x)),
max: new LuaBuiltinFunction((_sf, ...args: number[]) => Math.max(...args)),
min: new LuaBuiltinFunction((_sf, ...args: number[]) => Math.min(...args)),
// Rounding and remainder
fmod: new LuaBuiltinFunction((_sf, x: number, y: number) => x % y),
modf: new LuaBuiltinFunction((_sf, x: number) => {
const int = Math.floor(x);
const frac = x - int;
return new LuaTable([int, frac]);
}),
// Power and logarithms
exp: new LuaBuiltinFunction((_sf, x: number) => Math.exp(x)),
log: new LuaBuiltinFunction((_sf, x: number, base?: number) => {
if (base === undefined) {
return Math.log(x);
}
return Math.log(x) / Math.log(base);
}),
pow: new LuaBuiltinFunction((_sf, x: number, y: number) => Math.pow(x, y)),
sqrt: new LuaBuiltinFunction((_sf, x: number) => Math.sqrt(x)),
// Trigonometric functions
cos: new LuaBuiltinFunction((_sf, x: number) => Math.cos(x)),
sin: new LuaBuiltinFunction((_sf, x: number) => Math.sin(x)),
tan: new LuaBuiltinFunction((_sf, x: number) => Math.tan(x)),
acos: new LuaBuiltinFunction((_sf, x: number) => Math.acos(x)),
asin: new LuaBuiltinFunction((_sf, x: number) => Math.asin(x)),
atan: new LuaBuiltinFunction((_sf, y: number, x?: number) => {
if (x === undefined) {
return Math.atan(y);
}
return Math.atan2(y, x);
}),
// Hyperbolic functions
cosh: new LuaBuiltinFunction((_sf, x: number) => Math.cosh(x)),
sinh: new LuaBuiltinFunction((_sf, x: number) => Math.sinh(x)),
tanh: new LuaBuiltinFunction((_sf, x: number) => Math.tanh(x)),
// Additional utility
deg: new LuaBuiltinFunction((_sf, x: number) => x * 180 / Math.PI),
rad: new LuaBuiltinFunction((_sf, x: number) => x * Math.PI / 180),
ult: new LuaBuiltinFunction((_sf, m: number, n: number) => {
// Unsigned less than comparison
return (m >>> 0) < (n >>> 0);
}),
// Keep the cosine_similarity utility function
cosine_similarity: new LuaBuiltinFunction(
(sf, vecA: LuaTable | number[], vecB: LuaTable | number[]) => {
// Convert LuaTable to number[]
if (vecA instanceof LuaTable) {
vecA = vecA.toJSArray();
}
if (vecB instanceof LuaTable) {
vecB = vecB.toJSArray();
}
if (vecA.length !== vecB.length) {
throw new LuaRuntimeError("Vectors must be of the same length", sf);
}
let dotProduct = 0;
let normA = 0;
let normB = 0;
for (let i = 0; i < vecA.length; i++) {
dotProduct += vecA[i] * vecB[i];
normA += vecA[i] ** 2;
normB += vecB[i] ** 2;
}
return dotProduct / (Math.sqrt(normA) * Math.sqrt(normB));
},
),
});