aboutsummaryrefslogtreecommitdiff
path: root/lib/core/math.nom
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2019-01-14 15:42:48 -0800
committerBruce Hill <bruce@bruce-hill.com>2019-01-14 15:43:24 -0800
commitc1c32688a4afc43f6addb99b8b5fa878944a70e3 (patch)
treec886f21b5b08a9053aa74fcba4b241dae5ede76d /lib/core/math.nom
parent2309b696fc34b24f05f6658b94f9105ca8ee76e4 (diff)
Overhaul in progress, mostly working. Moved all the nomsu packages into
lib/, including core/*. Changes to how nomsu environments and importing work.
Diffstat (limited to 'lib/core/math.nom')
-rw-r--r--lib/core/math.nom212
1 files changed, 212 insertions, 0 deletions
diff --git a/lib/core/math.nom b/lib/core/math.nom
new file mode 100644
index 0000000..685ab1e
--- /dev/null
+++ b/lib/core/math.nom
@@ -0,0 +1,212 @@
+#!/usr/bin/env nomsu -V6.14
+#
+ This file defines some common math literals and functions
+
+use "core/metaprogramming"
+use "core/text"
+use "core/operators"
+use "core/control_flow"
+use "core/collections"
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+# Literals:
+test:
+ unless (all of [inf, NaN, pi, tau, golden ratio, e]):
+ fail "math constants failed"
+ $nan = (NaN)
+ unless ($nan != $nan):
+ fail "NaN failed"
+[infinity, inf] all compile to "math.huge"
+[not a number, NaN, nan] all compile to "(0/0)"
+[pi, Pi, PI] all compile to "math.pi"
+[tau, Tau, TAU] all compile to "(2*math.pi)"
+(golden ratio) compiles to "((1+math.sqrt(5))/2)"
+(e) compiles to "math.exp(1)"
+
+# Functions:
+test:
+ assume (("5" as a number) == 5)
+external $($ as a number) = $(tonumber $)
+external $($ as number) = $(tonumber $)
+test:
+ unless
+ all of [
+ abs 5, | 5 |, sqrt 5, √ 5, sine 5, cosine 5, tangent 5, arc sine 5, arc cosine 5
+ arc tangent 5, arc tangent 5 / 10, hyperbolic sine 5, hyperbolic cosine 5
+ hyperbolic tangent 5, e^ 5, ln 5, log 5 base 2, floor 5, ceiling 5, round 5
+ ]
+ ..:
+ fail "math functions failed"
+external [$(absolute value $), $(absolute value of $), $(| $ |), $(abs $)] =
+ [$math.abs, $math.abs, $math.abs, $math.abs]
+external [$(square root $), $(square root of $), $(√ $), $(sqrt $)] =
+ [$math.sqrt, $math.sqrt, $math.sqrt, $math.sqrt]
+external [$(sine $), $(sin $)] = [$math.sin, $math.sin]
+external [$(cosine $), $(cos $)] = [$math.cos, $math.cos]
+external [$(tangent $), $(tan $)] = [$math.tan, $math.tan]
+external [$(arc sine $), $(asin $)] = [$math.asin, $math.asin]
+external [$(arc cosine $), $(acos $)] = [$math.acos, $math.acos]
+external [$(arc tangent $), $(atan $)] = [$math.atan, $math.atan]
+external [$(arc tangent $y / $x), $(atan2 $y $x)] = [$math.atan2, $math.atan2]
+external [$(hyperbolic sine $), $(sinh $)] = [$math.sinh, $math.sinh]
+external [$(hyperbolic cosine $), $(cosh $)] = [$math.cosh, $math.cosh]
+external [$(hyperbolic tangent $), $(tanh $)] = [$math.tanh, $math.tanh]
+external [$(e^ $), $(exp $)] = [$math.exp, $math.exp]
+external [$(natural log $), $(ln $), $(log $), $(log $ base $)] = [$math.log, $math.log, $math.log, $math.log]
+external $(floor $) = $math.floor
+external [$(ceiling $), $(ceil $)] = [$math.ceil, $math.ceil]
+externally [round $, $ rounded] all mean
+ floor ($ + 0.5)
+test:
+ unless ((463 to the nearest 100) == 500): fail "rounding failed"
+ unless ((2.6 to the nearest 0.25) == 2.5): fail "rounding failed"
+
+externally ($n to the nearest $rounder) means
+ $rounder * (floor ($n / $rounder + 0.5))
+
+# Any/all
+externally [all of $items, all $items] all mean:
+ for $ in $items:
+ unless $:
+ return (no)
+ return (yes)
+[not all of $items, not all $items] all parse as (not (all of $items))
+externally [any of $items, any $items] all mean:
+ for $ in $items:
+ if $:
+ return (yes)
+ return (no)
+[none of $items, none $items] all parse as (not (any of $items))
+
+# Sum/product
+externally [sum of $items, sum $items] all mean:
+ $total = 0
+ for $ in $items:
+ $total += $
+ return $total
+
+externally [product of $items, product $items] all mean:
+ $prod = 1
+ for $ in $items:
+ $prod *= $
+ return $prod
+
+externally [avg of $items, average of $items] all mean
+ (sum of $items) / (size of $items)
+
+# Min/max
+externally [min of $items, smallest of $items, lowest of $items] all mean:
+ $best = (nil)
+ for $ in $items:
+ if (($best == (nil)) or ($ < $best)): $best = $
+ return $best
+
+externally [
+ max of $items, biggest of $items, largest of $items, highest of $items
+] all mean:
+ $best = (nil)
+ for $ in $items:
+ if (($best == (nil)) or ($ > $best)): $best = $
+ return $best
+
+test:
+ assume ((min of [3, -4, 1, 2] by $ = ($ * $)) == 1)
+ assume ((max of [3, -4, 1, 2] by $ = ($ * $)) == -4)
+
+(min of $items by $item = $value_expr) parses as
+ result of:
+ $best = (nil)
+ $best_key = (nil)
+ for $item in $items:
+ $key = $value_expr
+ if (($best == (nil)) or ($key < $best_key)):
+ $best = $item
+ $best_key = $key
+ return $best
+
+(max of $items by $item = $value_expr) parses as
+ result of:
+ $best = (nil)
+ $best_key = (nil)
+ for $item in $items:
+ $key = $value_expr
+ if (($best == (nil)) or ($key > $best_key)):
+ $best = $item
+ $best_key = $key
+ return $best
+
+test:
+ assume (100 clamped between 0 and 10) == 10
+
+externally ($ clamped between $min and $max) means:
+ when:
+ ($ < $min):
+ return $min
+
+ ($ > $max):
+ return $max
+
+ else:
+ return $
+
+test:
+ assume (-0.1 smoothed by 2.7) == 0
+ assume (0 smoothed by 2.7) == 0
+ assume (0.5 smoothed by 2.7) == 0.5
+ assume (1 smoothed by 2.7) == 1
+ assume (1.1 smoothed by 2.7) == 1
+
+externally ($ smoothed by $smoothness) means:
+ $ = ($ clamped between 0 and 1)
+ if ($smoothness == 0): return $
+ $k = (2 ^ $smoothness)
+ if ($ < 0.5):
+ return (0.5 * (2 * $) ^ $k)
+ ..else:
+ return (1 - 0.5 * (2 - 2 * $) ^ $k)
+
+test:
+ assume (5 to 7 mixed by -1.0) == 5
+ assume (5 to 7 mixed by 0.0) == 5
+ assume (5 to 7 mixed by 0.5) == 6
+ assume (5 to 7 mixed by 1.0) == 7
+ assume (5 to 7 mixed by 2.0) == 7
+
+externally ($lo to $hi mixed by $amount) means:
+ $ = ($amount clamped between 0 and 1)
+ return ((1 - $) * $lo + $ * $hi)
+
+test:
+ assume ([0, 1, 11] mixed by 0.0) == 0
+ assume ([0, 1, 11] mixed by 0.25) == 0.5
+ assume ([0, 1, 11] mixed by 0.5) == 1
+ assume ([0, 1, 11] mixed by 0.75) == 6
+ assume ([0, 1, 11] mixed by 1.0) == 11
+ assume ([99] mixed by 0.5) == 99
+
+externally ($nums mixed by $amount) means:
+ $ = ($amount clamped between 0 and 1)
+ $i = (1 + ($ * ((#$nums) - 1)))
+ if ((floor $i) == (#$nums)):
+ return $nums.(floor $i)
+ [$lo, $hi] = [$nums.(floor $i), $nums.(floor ($i + 1))]
+ return ($lo to $hi mixed by ($i mod 1))
+
+# Random functions
+externally (seed random with $) means:
+ lua> ("
+ math.randomseed(\$);
+ for i=1,20 do math.random(); end
+ ")
+(seed random) parses as (seed random with (=lua "os.time()"))
+[random number, random, rand] all compile to "math.random()"
+[random int $n, random integer $n, randint $n] all compile to
+ "math.random(\($n as lua expr))"
+
+[random from $low to $high, random number from $low to $high, rand $low $high]
+..all compile to "math.random(\($low as lua expr), \($high as lua expr))"
+
+externally [
+ random choice from $elements, random choice $elements, random $elements
+] all mean (=lua "\$elements[math.random(#\$elements)]")