aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorMarvin Borner2024-05-02 21:57:58 +0200
committerMarvin Borner2024-05-02 21:57:58 +0200
commita25ed8a75d036de252cfe74b5fa0788215194b41 (patch)
tree65ab549fe20b719535113a4af40bd4c784765cbb
parent349e8574c67bf575ed39694c8085eab00473bfaa (diff)
More math
MAATHTHAHHAHA
-rw-r--r--docs/code.js2
-rw-r--r--docs/index.html2
-rw-r--r--editors/vim/syntax/bruijn.vim4
-rw-r--r--samples/euler/007.bruijn2
-rw-r--r--samples/fun/pi-rational.bruijn28
-rw-r--r--samples/rosetta/fibonacci_sequence.bruijn2
-rw-r--r--src/Parser.hs6
-rw-r--r--std/List.bruijn11
-rw-r--r--std/Math.bruijn18
-rw-r--r--std/Math/Complex.bruijn35
-rw-r--r--std/Math/Rational.bruijn7
-rw-r--r--std/Math/Real.bruijn68
-rw-r--r--std/Number/Conversion.bruijn2
-rw-r--r--std/Number/Parigot.bruijn24
-rw-r--r--std/Number/Scott.bruijn31
-rw-r--r--std/Number/Ternary.bruijn8
-rw-r--r--std/Number/Unary.bruijn3
-rw-r--r--std/Number/Wadsworth.bruijn23
18 files changed, 234 insertions, 42 deletions
diff --git a/docs/code.js b/docs/code.js
index 8fd7158..599068e 100644
--- a/docs/code.js
+++ b/docs/code.js
@@ -11,7 +11,7 @@ const term = (t) =>
.replaceAll(/'([^\'])'/g, "<span class='string'>'$1'</span>")
.replaceAll(/"([^\"]*)"/g, "<span class='string'>\"$1\"</span>")
.replaceAll(
- /(\([+-][0-9]+\.[0-9]+[frc]?\))/g,
+ /(\([+-][0-9]+\.[0-9]+[qr]?\))/g,
"<span class='number'>$1</span>",
)
.replaceAll(/(\([+-][0-9]+[ubtd]?\))/g, "<span class='number'>$1</span>")
diff --git a/docs/index.html b/docs/index.html
index 837492f..931b706 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -153,7 +153,7 @@ in std/Number/Unary.bruijn:35
<li>
Compiled binary lambda calculus is incredibly expressive and tiny.
Read the articles by
- <a href="https://justine.lol/lambda/#why">Justine</a> and
+ <a href="https://justine.lol/lambda/#why">Jart</a> and
<a href="https://tromp.github.io/cl/cl.html">Tromp</a>.
</li>
<li>
diff --git a/editors/vim/syntax/bruijn.vim b/editors/vim/syntax/bruijn.vim
index fbe7a47..4f20593 100644
--- a/editors/vim/syntax/bruijn.vim
+++ b/editors/vim/syntax/bruijn.vim
@@ -10,8 +10,8 @@ syn match bruijnAbstraction /[[\]]/
syn match bruijnIndex /\([^0-9A-Za-z]\)\@<=\d\([^0-9]\)\@=/
syn match bruijnChar /'\@<=.'\@=/
syn match bruijnNumber /([+-]\d\+[dubt]\?)/
-syn match bruijnFloat /([+-]\d\+\.\d\+[fr]\?)/
-syn match bruijnComplex /([+-]\d\+\.\d\+i[+-]\d\+\.\d\+)/
+syn match bruijnFloat /([+-]\d\+\.\d\+[qr]\?)/
+syn match bruijnComplex /([+-]\d\+\.\d\+[+-]\d\+\.\d\+i)/
syn match bruijnDefinition /^\t*\S\+/
syn match bruijnType /\( ⧗ \)\@<=.*$/
syn match bruijnTypeDelim / ⧗ /
diff --git a/samples/euler/007.bruijn b/samples/euler/007.bruijn
index 6d05451..c14b41f 100644
--- a/samples/euler/007.bruijn
+++ b/samples/euler/007.bruijn
@@ -4,7 +4,7 @@
:import std/Math .
:import std/List .
-solve dec → (\index primes)
+solve dec → (index primes)
:test ((solve (+6)) =? (+13)) ([[1]])
diff --git a/samples/fun/pi-rational.bruijn b/samples/fun/pi-rational.bruijn
new file mode 100644
index 0000000..245f45f
--- /dev/null
+++ b/samples/fun/pi-rational.bruijn
@@ -0,0 +1,28 @@
+:import std/Pair .
+:import std/Combinator .
+:import std/Number/Unary .
+
+qadd &[[&[[p : q]]]] ⧗ Rational → Rational → Rational
+ p (3 ⋅ ++0) + (1 ⋅ ++2)
+ q (2 ⋅ 0) + (2 + 0)
+
+fac [[1 [[0 (1 [[2 1 (1 0)]])]] [1] i]] ⧗ Unary → Unary
+
+# challenge: smallest, yet fastest converging, π ratio calculation
+
+# naive
+v1-pi/2 [0 &[[op]] start [[1]]]
+ start ((+0u) : (+0u)) : (+0u)
+ op (qadd 1 (enum : --denom)) : ++0
+ enum (0 (+2u)) ⋅ ((+2u) (fac 0))
+ denom fac ++((+2u) ⋅ 0)
+
+dfac [[1 [[0 (1 [[2 1 (1 (1 0))]])]] [1] i]] ⧗ Unary → Unary
+
+# double factorial
+# dfac and fac could be shared!
+v2-pi/2 [0 &[[op]] start [[1]]]
+ start ((+0u) : (+0u)) : (+0u)
+ op (qadd 1 (enum : --denom)) : ++0
+ enum fac 0
+ denom dfac ++0
diff --git a/samples/rosetta/fibonacci_sequence.bruijn b/samples/rosetta/fibonacci_sequence.bruijn
index d2e4752..dc64962 100644
--- a/samples/rosetta/fibonacci_sequence.bruijn
+++ b/samples/rosetta/fibonacci_sequence.bruijn
@@ -8,7 +8,7 @@ fib-unary [0 [[[2 0 [2 (1 0)]]]] k i]
:test (fib-unary (+6u)) ((+8u))
# ternary fibonacci using infinite list iteration (very fast)
-fib-list \index fibs
+fib-list index fibs
fibs head <$> (iterate &[[0 : (1 + 0)]] ((+0) : (+1)))
:test (fib-list (+6)) ((+8))
diff --git a/src/Parser.hs b/src/Parser.hs
index a24db6f..0274906 100644
--- a/src/Parser.hs
+++ b/src/Parser.hs
@@ -149,11 +149,11 @@ parseFloat :: Parser Expression
parseFloat = do
_ <- string "(" <?> "float start"
num <- signedFloat <?> "signed float"
- base <- try (oneOf "fr") <|> return 'f'
+ base <- try (oneOf "qr") <|> return 'q'
_ <- string ")" <?> "float end"
pure $ f base num
where
- f 'f' = floatToRational
+ f 'q' = floatToRational
f 'r' = floatToReal
f _ = invalidProgramState
sign :: Parser (Rational -> Rational)
@@ -171,8 +171,8 @@ parseComplex :: Parser Expression
parseComplex = do
_ <- string "(" <?> "complex start"
real <- signedFloat <?> "signed complex"
- _ <- char 'i'
imaginary <- signedFloat <?> "signed complex"
+ _ <- char 'i'
_ <- string ")" <?> "complex end"
pure $ floatToComplex real imaginary
where
diff --git a/std/List.bruijn b/std/List.bruijn
index 799e966..d8d7dc9 100644
--- a/std/List.bruijn
+++ b/std/List.bruijn
@@ -89,11 +89,11 @@ index-unary [[P.fst (0 P.snd 1)]] ⧗ (List a) → Unary → a
# returns the element at index in list
index z [[[rec]]] ⧗ (List a) → Number → a
- rec 0 [[[case-index]]] case-end
- case-index =?4 2 (5 --4 1)
+ rec 1 [[[case-index]]] case-end
+ case-index =?3 2 (5 1 --3)
case-end empty
-…!!… \index
+…!!… index
:test (((+1) : ((+2) : {}(+3))) !! (+0)) ((+1))
:test (((+1) : ((+2) : {}(+3))) !! (+2)) ((+3))
@@ -519,12 +519,15 @@ iterate z [[[rec]]] ⧗ (a → a) → a → (List a)
:test (take (+5) (iterate i (+4))) (take (+5) (repeat (+4)))
:test (take (+0) (iterate ++‣ (+0))) (empty)
+# TODO: performance
+nth-iterate index ∘∘ iterate
+
# enumerate list
enumerate zip (iterate ++‣ (+0)) ⧗ (List a) → (List (Pair Number a))
:test (enumerate "abc") (((+0) : 'a') : (((+1) : 'b') : {}((+2) : 'c')))
-# calculates all fixed points of given function as a list
+# calculates all fixed points of given functions as a list
y* [[[0 1] <$> 0] xs] ⧗ (List a) → (List b)
xs [[1 <! ([[1 2 0]] <$> 0)]] <$> 0
diff --git a/std/Math.bruijn b/std/Math.bruijn
index 3dcb23b..3e32bef 100644
--- a/std/Math.bruijn
+++ b/std/Math.bruijn
@@ -162,7 +162,7 @@ arrow z [[[[rec]]]] ⧗ Number → Number → Number → Number
# TODO: faster fib?
fibs L.map L.head (L.iterate &[[0 : (1 + 0)]] ((+0) : (+1))) ⧗ (List Number)
-fib [L.index ++0 fibs] ⧗ Number
+fib [L.index fibs ++0] ⧗ Number
:test (fib (+5)) ((+8))
@@ -238,12 +238,10 @@ factors \divs primes ⧗ Number → (List Number)
# TODO: faster!
# → BBP/Bellard's formula with ternary base?
# TODO: |log|, better primes/mod/div
-π g (+1) (+180) (+60) (+2) ⧗ (List Number)
- g z [[[[[calc]]]]]
- calc b : (4 q r t i)
- a ↑⁰(↑⁺0 ⋅ (↑⁰0 + (+2)))
- b (3 ⋅ ↑⁰(↑⁻(↑⁻0)) + ((+5) ⋅ 2)) / ((+5) ⋅ 1)
- q (+10) ⋅ 3 ⋅ 0 ⋅ --((+2) ⋅ 0)
- r (+10) ⋅ a ⋅ (3 ⋅ ((+5) ⋅ 0 - (+2)) + 2 - (b ⋅ 1))
- t 1 ⋅ a
- i ++0
+π y [[[[[calc]]]]] (+1) (+180) (+60) (+2) ⧗ (List Number)
+ calc [[0 : (6 q r t ++2)]] a b
+ a ↑⁰(↑⁺0 ⋅ (↑⁰0 + (+2)))
+ b (3 ⋅ ↑⁰(↑⁻(↑⁻0)) + ((+5) ⋅ 2)) / ((+5) ⋅ 1)
+ q (+10) ⋅ 5 ⋅ 2 ⋅ --((+2) ⋅ 2)
+ r (+10) ⋅ 1 ⋅ (5 ⋅ ((+5) ⋅ 2 - (+2)) + 4 - (0 ⋅ 3))
+ t 3 ⋅ 1
diff --git a/std/Math/Complex.bruijn b/std/Math/Complex.bruijn
index a20717f..d3b5a7d 100644
--- a/std/Math/Complex.bruijn
+++ b/std/Math/Complex.bruijn
@@ -5,9 +5,29 @@
:import std/Pair .
:import std/Math/Real R
-ι (+0.0r) : (+1.0r)
+ι (+0.0+1.0i)
-# returns true of two complex numbers are equal approximately
+# converts a balanced ternary number to a complex number
+number→complex [[0 (R.number→real 1) (+0.0r)]] ⧗ Number → Complex
+
+:test (number→complex (+5)) ((+5.0+0.0i))
+
+# returns real part of a complex number
+real fst ⧗ Complex → Real
+
+:test (real (+5.0+2.0i)) ((+5.0r))
+
+# returns imaginary part of a complex number
+imag snd ⧗ Complex → Real
+
+:test (imag (+5.0+2.0i)) ((+2.0r))
+
+# approximates complex number by turning it into a pair of rationals
+approx &[[[(2 0) : (1 0)]]] ⧗ Complex → Number → (Pair Rational Rational)
+
+:test (approx (+5.0+2.0i) (+2)) ((+5.0q) : (+2.0q))
+
+# returns true if two complex numbers are equal approximately
approx-eq? [[[R.approx-eq? 2 (1 2) (0 2)]]] ⧗ Number → Complex → Complex → Boolean
# TODO: bigger value (higher performance first!)
@@ -48,3 +68,14 @@ invert &[[p : q]] ⧗ Complex → Complex
q R.div 0 (R.add (R.mul 1 1) (R.mul 0 0))
~‣ invert
+
+# ---
+
+:import std/List L
+
+# power function: complex^number
+pow-n [L.nth-iterate (mul 0) (+1.0+0.0i)] ⧗ Complex → Number → Complex
+
+ln [p : q] ⧗ Complex → Complex
+ p R.ln (&R.hypot 0)
+ q &R.atan2 0
diff --git a/std/Math/Rational.bruijn b/std/Math/Rational.bruijn
index 54c3a88..f1509b0 100644
--- a/std/Math/Rational.bruijn
+++ b/std/Math/Rational.bruijn
@@ -3,6 +3,7 @@
# (p : q) ⇔ (1 / (q + 1))
+:import std/Logic .
:import std/Combinator .
:import std/Logic .
:import std/Pair .
@@ -91,6 +92,10 @@ div [[1 ⋅ ~0]] ⧗ Rational → Rational → Rational
:test ((+8.0) / (+4.0) =? (+2.0)) (true)
:test ((+18.0) / (+12.0) =? (+1.5)) (true)
+gt? &[[&[[(N.gt? 1 3) ⋀? (N.gt? 0 2)]]]]
+
+lt? &[[&[[(N.lt? 1 3) ⋀? (N.lt? 0 2)]]]]
+
# increments a rational number
inc add (+1.0) ⧗ Rational → Rational
@@ -106,4 +111,4 @@ dec \sub (+1.0) ⧗ Rational → Rational
:import std/List L
# power function: rational^number
-pow-n [L.…!!… (L.iterate (mul 0) (+1.0))] ⧗ Rational → Number → Rational
+pow-n [L.nth-iterate (mul 0) (+1.0)] ⧗ Rational → Number → Rational
diff --git a/std/Math/Real.bruijn b/std/Math/Real.bruijn
index 49f4a92..28bc512 100644
--- a/std/Math/Real.bruijn
+++ b/std/Math/Real.bruijn
@@ -91,41 +91,79 @@ dec \sub (+1.0r) ⧗ Real → Real
:import std/List L
-# ∑(1/n^2)
-# converges to 1.6449...
-unary-1/n² [0 &[[(Q.add 1 op) : N.++0]] start [[0]]] ⧗ Real
- op (+1) : N.--(N.mul 0 0)
- start (+0.0f) : (+1)
-
-# e^x using Taylor expansion: ∑(x^n/n!) = e^x
+# e^x using Taylor expansion
+# tex: \sum_{n=0}^\infty \frac{x^n}{n!}
unary-exp [[0 &[[[[[[[2 1 0 (Q.add 4 (1 : N.--0)) N.++3]] pow fac]]]]] start [[[[1]]]]]] ⧗ Number → Real
pow N.mul 6 4
fac N.mul 1 3
- start [0 (+1) (+1) (+1.0f) (+1)]
+ start [0 (+1) (+1) (+1.0q) (+1)]
# equivalent to unary-exp but with ternary index using infinite list iteration
-exp [[L.index 0 (L.iterate &[[[[op]]]] start) [[[[1]]]] 0]] ⧗ Real → Real
+exp [[L.nth-iterate &[[[[op]]]] start 0 [[[[1]]]] 0]] ⧗ Real → Real
start [0 (+1.0r) (+1.0r) (+1.0r) (+1)]
op [[[2 1 0 (4 + (1 / 0)) N.++3]] pow fac]
pow 6 ⋅ 4
fac (number→real 1) ⋅ 3
# power function: real^number
-pow-n [L.…!!… (L.iterate (mul 0) (+1.0r))] ⧗ Real → Number → Real
+pow-n [L.nth-iterate (mul 0) (+1.0r)] ⧗ Real → Number → Real
-# e^x using infinite limit: lim (1+x/n)^n, n to ∞
+# e^x using infinite limit
+# tex: \lim_{n\to\infty}(1+x/n)^n
lim-exp [[pow-n [(N.add 2 1) : N.--1] 0]] ⧗ Number → Real
-# log_e using Taylor expansion
-ln [[[L.index 1 (L.iterate &[[[op]]] start)] (--1 / ++1 0) [[[1]]]]] ⧗ Real → Real
- start [0 1 (+0.0f) (+0)]
+# natural logarithm using Taylor expansion
+# tex: \sum_{n=0}^\infty\frac{2}{2n+1}(\frac{x-1}{x+1})^{2n+1}
+# error: O((x-1)/2)^{2n+1}
+ln [[[L.nth-iterate &[[[op]]] start 1] (--1 / ++1 0) [[[1]]]]] ⧗ Real → Real
+ start [0 1 (+0.0q) (+0)]
op [0 pow (Q.add 2 go) N.++1]
- pow Q.mul 3 (Q.pow-n 4 (+2))
+ pow Q.mul 3 (Q.mul 4 4)
go Q.mul ((+2) : (N.mul (+2) 1)) 3
+:test (Q.eq? (ln (+2.0r) (+2)) ((+168) : (+242))) (true)
+
derive [[[[((3 (0 + 1)) - (3 0)) / 1]] ((+1.0r) / 0) 0]] ⧗ (Real → Real) → (Real → Real)
# power function: real^real
pow [[exp (0 ⋅ (ln 1))]] ⧗ Real → Real → Real
…**… pow
+
+# square root by x^{0.5}
+sqrt* \pow (+0.5r) ⧗ Real → Real
+
+# Newton's/Heron's method, quadratic convergence
+# tex: x_{n+1}=\frac{x_n+a/x_n}{2}
+sqrt [[y [[[N.=?0 guess go]]] (1 0) 0]] ⧗ Real → Real
+ guess (+1.0q)
+ go [Q.div (Q.add 0 (Q.div 2 0)) (+2.0q)] (2 1 N.--0)
+
+# hypotenuse
+hypot [[sqrt ((0 ⋅ 0) + (1 ⋅ 1))]] ⧗ Real → Real → Real
+
+# tex: \sum_{n=0}^\infty\frac{2^n n!^2}{(2n+1)!}
+π/2 [L.nth-iterate &[[[[[op]]]]] start 0 [[[[[3]]]]]] ⧗ Real
+ start [0 (+1) (+0.0q) (+1) (+1) (+1)]
+ op [0 N.++5 (Q.add 4 ((N.mul 3 2) : N.--1)) enum-pow enum-fac denom]
+ enum-pow N.mul 3 (+2)
+ enum-fac N.mul 2 (N.mul 5 5)
+ denom [N.mul 2 (N.mul 0 N.++0)] (N.mul (+2) 5)
+
+# ratio of circle's circumference to its diameter
+# TODO: Gauss-Legendre
+π π/2 ⋅ (+2.0r) ⧗ Real
+
+# arctan by Taylor expansion, only for |x|<=1
+# tex: \sum_{n=0}^\infty(-1)^n \frac{x^{2n+1}}{2n+1}
+arctan* [[[L.nth-iterate &[[[[op]]]] start 1] (1 0) [[[[3]]]]]] ⧗ Real → Real
+ start [0 1 [[0]] (Q.pow-n 1 (+3)) (+3.0q)]
+ op [0 ((3 Q.add Q.sub) 4 (Q.div 2 1)) \3 enum denom]
+ enum Q.mul 2 (Q.mul 5 5)
+ denom Q.add 1 (+2.0q)
+
+# actual arctan for arbitrary x
+arctan [[Q.sub (π/2 0) (arctan* [Q.div (+1.0q) (2 1)] 0)]] ⧗ Real → Real
+
+# TODO: atan2
+atan2 [0] ⧗ Real → Real
diff --git a/std/Number/Conversion.bruijn b/std/Number/Conversion.bruijn
index 52f3c9e..01c7e9f 100644
--- a/std/Number/Conversion.bruijn
+++ b/std/Number/Conversion.bruijn
@@ -14,6 +14,8 @@ unary→ternary [0 T.inc (+0t)] ⧗ Unary → Ternary
:test (¹³(+0u)) ((+0t))
:test (¹³(+2u)) ((+2t))
+binary→unary [[0 (+0u) [U.inc (2 0)] 1]] (U.mul (+2u)) ⧗ Binary → Unary
+
# converts ternary numbers to unary
ternary→unary [T.apply 0 U.inc (+0u)] ⧗ Ternary → Unary
diff --git a/std/Number/Parigot.bruijn b/std/Number/Parigot.bruijn
new file mode 100644
index 0000000..9a23fd4
--- /dev/null
+++ b/std/Number/Parigot.bruijn
@@ -0,0 +1,24 @@
+# MIT License, Copyright (c) 2024 Marvin Borner
+# see "on the representation of data in lambda-calculus" #5
+# has a "one-step" predecessor *and* addition function
+# has 2x space complexity compared to unary/Church
+
+zero [0]
+
+inc [[[0 2 1]]]
+
+++‣ inc
+
+dec [[1 0 [0]]]
+
+--‣ dec
+
+:test (dec (inc zero)) (zero)
+
+iter [[[0 ι ρ ρ]]]
+ ρ [[3 (1 0 0)]]
+ ι [[4]]
+
+rec [[[0 ι ρ ρ --0]]]
+ ρ [[[4 0 (2 1 1)]]]
+ ι [[[5]]]
diff --git a/std/Number/Scott.bruijn b/std/Number/Scott.bruijn
new file mode 100644
index 0000000..bc776d8
--- /dev/null
+++ b/std/Number/Scott.bruijn
@@ -0,0 +1,31 @@
+# MIT License, Copyright (c) 2023 Marvin Borner
+
+:import std/Combinator .
+:import std/Logic .
+
+zero [[1]] ⧗ Scott
+
+inc [[[0 2]]] ⧗ Scott → Scott
+
+:test (inc zero) ([[0 zero]])
+:test (inc (inc zero)) ([[0 [[0 zero]]]])
+:test (inc (inc (inc zero))) ([[0 [[0 [[0 zero]]]]]])
+
+dec [0 zero [0]] ⧗ Scott → Scott
+
+:test (dec zero) (zero)
+:test (dec (inc zero)) (zero)
+:test (dec (inc (inc zero))) (inc zero)
+
+zero? [0 true [false]] ⧗ Scott → Boolean
+
+:test (zero? zero) (true)
+:test (zero? (inc zero)) (false)
+:test (zero? (inc (inc zero))) (false)
+
+add z [[[1 0 [inc (3 0 1)]]]] ⧗ Scott → Scott → Scott
+
+:test (add zero zero) (zero)
+:test (add zero (inc zero)) (inc zero)
+:test (add (inc zero) zero) (inc zero)
+:test (add (inc zero) (inc zero)) (inc (inc zero))
diff --git a/std/Number/Ternary.bruijn b/std/Number/Ternary.bruijn
index 27da643..2ad5059 100644
--- a/std/Number/Ternary.bruijn
+++ b/std/Number/Ternary.bruijn
@@ -328,7 +328,7 @@ abs [<?0 -0 0] ⧗ Number → Number
:test (|(-1)) ((+1))
:test (|(+42)) ((+42))
-# apply a function n times to a value
+# applies a function n times to a value
# ~> substitute church numbers
apply z [[[rec]]] ⧗ Number → (a → a) → a → a
rec =?1 case-end case-apply
@@ -382,6 +382,12 @@ log₃ log₃* ∘ strip ⧗ Number → Number
:test (log₃ (+5)) ((+3))
:test (log₃ (+42)) ((+5))
+# amount of non-zero trits
+hamming-weight [0 (+0) inc inc [0]] ⧗ Number → Number
+
+:test ((hamming-weight (+5)) =? (+3)) (true)
+:test ((hamming-weight (+6)) =? (+2)) (true)
+
# returns the smallest number in a range such that a predicate is true
binary-search z [[[[rec]]]] ⧗ (Number → Boolean) → Number → Number → Number
rec (0 =? 1) case-end case-search
diff --git a/std/Number/Unary.bruijn b/std/Number/Unary.bruijn
index ae54c19..b764e87 100644
--- a/std/Number/Unary.bruijn
+++ b/std/Number/Unary.bruijn
@@ -143,6 +143,9 @@ pow [[0 [[3 (1 0)]] pow*]] ⧗ Unary → Unary → Unary
:test ((+2u) ^ (+3u)) ((+8u))
:test ((+3u) ^ (+2u)) ((+9u))
+# also note that
+# [0 ..i.. 0] (+nu) = n^..i..^n
+
# fibonacci sequence
# index +1 vs std/Math fib
fib [0 [[[2 0 [2 (1 0)]]]] [[1]] [0]] ⧗ Unary → Unary
diff --git a/std/Number/Wadsworth.bruijn b/std/Number/Wadsworth.bruijn
new file mode 100644
index 0000000..00bd3c3
--- /dev/null
+++ b/std/Number/Wadsworth.bruijn
@@ -0,0 +1,23 @@
+# MIT License, Copyright (c) 2023 Marvin Borner
+# from Wadsworth's "some unusual numeral systems" (p224, see refs in README)
+
+:import std/Combinator .
+
+zero [0 [k]] ⧗ Wadsworth
+
+# increment Wadsworth number
+inc [[[2 [2 (1 0) 1]]]] ⧗ Wadsworth → Wadsworth
+
+:test (inc (inc zero)) ([[[2 (1 (0 (k [[1]]))) 1 0]]])
+
+# decrement Wadsworth number
+dec [[1 [k (1 0)] i]] ⧗ Wadsworth → Wadsworth
+
+:test (dec (dec (inc (inc zero)))) (zero)
+
+# returns true if Wadsworth number is zero
+zero? [0 i (k (k [[0]]))] ⧗ Wadsworth → Bool
+
+:test (zero? zero) ([[1]])
+:test (zero? (inc zero)) ([[0]])
+:test (zero? (inc (inc zero))) ([[0]])