From c1c32688a4afc43f6addb99b8b5fa878944a70e3 Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Mon, 14 Jan 2019 15:42:48 -0800 Subject: Overhaul in progress, mostly working. Moved all the nomsu packages into lib/, including core/*. Changes to how nomsu environments and importing work. --- lib/core/math.nom | 212 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 212 insertions(+) create mode 100644 lib/core/math.nom (limited to 'lib/core/math.nom') 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)]") -- cgit v1.2.3