class M{ static inv_lerp(from, to, value){ //if the range are numbers, we assume the interpolation value is too if(from is Num && to is Num) return (value - from) / (to - from) //if only one of the range qualifiers is a sequence, we make the other one a endless sequence of itself //(will do a union to take the shortest length anyways) if(from is Sequence != to is Sequence) { if(from is Sequence){ to = RepVal.new(to) } else { from = RepVal.new(from) } } //if the interpolation value is a number, make it infinite if(value is Num) value = RepVal.new(value) var result = [] Util.for_all([from, to, value]) { |from, to, value| result.add(inv_lerp(from, to, value)) } return result } static pow2(value){ return value * value } static lerp(from, to, value){ //if the range are numbers, we assume the interpolation value is too if(from is Num && to is Num) return from + (to - from) * value //if only one of the range qualifiers is a sequence, we make the other one a endless sequence of itself //(will do a union to take the shortest length anyways) if(from is Sequence != to is Sequence) { if(from is Sequence){ to = RepVal.new(to) } else { from = RepVal.new(from) } } //if the interpolation value is a number, make it infinite if(value is Num) value = RepVal.new(value) var result = [] Util.for_all([from, to, value]) { |from, to, value| result.add(lerp(from, to, value)) } return result } //not remainder!! //this is the cool modulo //the one that can deal with negative numbers not badly static mod(number, min, max){ return min + mod(number, max - min) } static mod(number, max){ return max.sign * ((number % max + max) % max) } static remap(min_in, max_in, min_out, max_out, value){ var inter = inv_lerp(min_in, max_in, value) return lerp(min_out, max_out, inter) } static clamp(value, min, max){ //if its a simple number, we assume so are the bounds if(value is Num){ return Math.max(Math.min(value, max), min) } //otherwise we assume its a sequence //if bounds are numbers, just use them if(min is Num && max is Num){ return value.map {|val| clamp(val, min, max)}.toList } if(min is Sequence && max is Sequence){ var result = [] Util.for_all([value, min, max]) { |v| result.add(clamp(v[0], v[1], v[2])) } return result } System.print("can't clamp %(value.type) between %(min.type) and %(max.type)") return null } static sqr_length(vector){ return vector.reduce(0){|sum, val| sum + val * val } } static length(vector){ return sqr_length(vector).sqrt } } import "math/vector" for Vector import "luxe: math" for Math import "math/repVal" for RepVal import "math/Util" for Util