aboutsummaryrefslogtreecommitdiffhomepage
path: root/std/Math
diff options
context:
space:
mode:
authorMarvin Borner2024-08-06 01:53:19 +0200
committerMarvin Borner2024-08-06 01:53:19 +0200
commit0c3b464d3c73fcd1a6fde3f2f5882eddd5c79685 (patch)
tree6ae5ac53ca8c4feff7902b0df9d6c5c94bf3eb87 /std/Math
parente2c3965f929556dda9f779c237f4ba96c8f6c542 (diff)
Complex updates
Diffstat (limited to 'std/Math')
-rw-r--r--std/Math/Complex.bruijn64
-rw-r--r--std/Math/Rational.bruijn50
-rw-r--r--std/Math/Real.bruijn63
3 files changed, 120 insertions, 57 deletions
diff --git a/std/Math/Complex.bruijn b/std/Math/Complex.bruijn
index d3b5a7d..03ae8d5 100644
--- a/std/Math/Complex.bruijn
+++ b/std/Math/Complex.bruijn
@@ -3,69 +3,60 @@
:import std/Combinator .
:import std/Pair .
+:import std/Number N
+:import std/Math/Rational Q
:import std/Math/Real R
-ι (+0.0+1.0i)
+i (+0.0+1.0i)
# converts a balanced ternary number to a complex number
-number→complex [[0 (R.number→real 1) (+0.0r)]] ⧗ Number → Complex
+number→complex [[(R.number→real 1 0) : ((+0.0r) 0)]] ⧗ Number → Complex
:test (number→complex (+5)) ((+5.0+0.0i))
# returns real part of a complex number
-real fst ⧗ Complex → Real
+real [[1 0 [[1]]]] ⧗ Complex → Real
:test (real (+5.0+2.0i)) ((+5.0r))
# returns imaginary part of a complex number
-imag snd ⧗ Complex → Real
+imag [[1 0 [[0]]]] ⧗ 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!)
-…≈?… approx-eq? (+1000)
-
# adds two complex numbers
-add &[[&[[(R.add 3 1) : (R.add 2 0)]]]] ⧗ Complex → Complex → Complex
+add φ &[[&[[(Q.add 3 1) : (Q.add 2 0)]]]] ⧗ Complex → Complex → Complex
…+… add
# subtracts two complex numbers
-sub &[[&[[(R.sub 3 1) : (R.sub 2 0)]]]] ⧗ Complex → Complex → Complex
+sub φ &[[&[[(Q.sub 3 1) : (Q.sub 2 0)]]]] ⧗ Complex → Complex → Complex
-…+… sub
+…-… sub
# multiplies two complex numbers
-mul &[[&[[p : q]]]] ⧗ Complex → Complex → Complex
- p R.sub (R.mul 3 1) (R.mul 2 0)
- q R.add (R.mul 3 0) (R.mul 2 1)
+mul φ &[[&[[p : q]]]] ⧗ Complex → Complex → Complex
+ p Q.sub (Q.mul 3 1) (Q.mul 2 0)
+ q Q.add (Q.mul 3 0) (Q.mul 2 1)
…⋅… mul
# divides two complex numbers
-div &[[&[[p : q]]]] ⧗ Complex → Complex → Complex
- p R.div (R.add (R.mul 3 1) (R.mul 2 0)) (R.add (R.mul 1 1) (R.mul 0 0))
- q R.div (R.sub (R.mul 2 1) (R.mul 1 0)) (R.add (R.mul 1 1) (R.mul 0 0))
+div φ &[[&[[p : q]]]] ⧗ Complex → Complex → Complex
+ p Q.div (Q.add (Q.mul 3 1) (Q.mul 2 0)) (Q.add (Q.mul 1 1) (Q.mul 0 0))
+ q Q.div (Q.sub (Q.mul 2 1) (Q.mul 3 0)) (Q.add (Q.mul 1 1) (Q.mul 0 0))
…/… div
# negates a complex number
-negate &[[(R.negate 1) : (R.negate 0)]] ⧗ Complex → Complex
+negate b &[[(Q.negate 1) : (Q.negate 0)]] ⧗ Complex → Complex
-‣ negate
# inverts a complex number
-invert &[[p : q]] ⧗ Complex → Complex
- p R.div 1 (R.add (R.mul 1 1) (R.mul 0 0))
- q R.div 0 (R.add (R.mul 1 1) (R.mul 0 0))
+invert b &[[p : q]] ⧗ Complex → Complex
+ p Q.div 1 (Q.add (Q.mul 1 1) (Q.mul 0 0))
+ q Q.div 0 (Q.add (Q.mul 1 1) (Q.mul 0 0))
~‣ invert
@@ -76,6 +67,17 @@ invert &[[p : q]] ⧗ Complex → Complex
# 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
+exp [[L.nth-iterate &[[[[op]]]] start 0 [[[[1]]]] 0]] ⧗ Complex → Complex
+ start [0 (+1.0+0.0i) (+1.0+0.0i) (+1.0+0.0i) (+1)]
+ op [[[2 1 0 (4 + (1 / 0)) N.++3]] pow fac]
+ pow 6 â‹… 4
+ fac 3 ⋅ (number→complex 1)
+
+ln [[[p : q] (1 0)]] ⧗ Complex → Complex
+ p R.ln (&[[R.hypot [2] [1]]] 0) 1
+ q &[[\R.atan2 [2] [1]]] 0 1
+
+# complex power function: complex^complex
+pow [[exp (0 ⋅ (ln 1))]] ⧗ Complex → Complex → Complex
+
+…**… pow
diff --git a/std/Math/Rational.bruijn b/std/Math/Rational.bruijn
index e72b6a9..3b7f461 100644
--- a/std/Math/Rational.bruijn
+++ b/std/Math/Rational.bruijn
@@ -1,11 +1,10 @@
# ideas by u/DaVinci103
# MIT License, Copyright (c) 2024 Marvin Borner
-# (p : q) ⇔ (1 / (q + 1))
+# (p : q) ⇔ (p / (q + 1))
:import std/Logic .
:import std/Combinator .
-:import std/Logic .
:import std/Pair .
:import std/Math N
@@ -24,6 +23,36 @@ eq? &[[&[[N.eq? (N.mul 3 N.++0) (N.mul N.++2 1)]]]] ⧗ Rational → Rational â†
:test ((+42.0) =? (+42.0)) (true)
:test ((+0.4) =? (+0.5)) (false)
+# returns true if a rational number is greater than another
+gt? &[[&[[N.gt? (N.mul 3 N.++0) (N.mul N.++2 1)]]]] ⧗ Rational → Rational → Boolean
+
+…>?… gt?
+
+# returns true if a rational number is less than another
+lt? &[[&[[N.lt? (N.mul 3 N.++0) (N.mul N.++2 1)]]]] ⧗ Rational → Rational → Boolean
+
+…<?… lt?
+
+# returns true if a rational number is positive
+positive? \gt? (+0.0) ⧗ Rational → Boolean
+
+>?‣ positive?
+
+# returns true if a real number is negative
+negative? \lt? (+0.0) ⧗ Rational → Boolean
+
+<?‣ negative?
+
+# returns true if a rational number is zero
+zero? &[[N.=?1]] ⧗ Rational → Boolean
+
+=?‣ zero?
+
+# negates a rational number if <0
+abs &[[N.|1 : N.|0]] ⧗ Rational → Rational
+
+|‣ abs
+
# finds smallest equivalent representation of a rational number
compress &[[[(N.div 2 0) : N.--(N.div N.++1 0)] (N.gcd 1 N.++0)]] ⧗ Rational → Rational
@@ -34,7 +63,7 @@ compress &[[[(N.div 2 0) : N.--(N.div N.++1 0)] (N.gcd 1 N.++0)]] ⧗ Rational â
# adds two rational numbers
add &[[&[[p : q]]]] ⧗ Rational → Rational → Rational
- p N.add (N.mul 3 N.++0) (N.mul 1 N.++2)
+ p N.add (N.mul 3 N.++0) (N.mul N.++2 1)
q N.add (N.mul 2 0) (N.add 2 0)
…+… add
@@ -43,15 +72,15 @@ add &[[&[[p : q]]]] ⧗ Rational → Rational → Rational
:test ((+1.8) + (+1.2) =? (+3.0)) (true)
:test ((-1.8) + (+1.2) =? (-0.6)) (true)
-reduce [[[(N.div 2 0) : N.--(N.div 1 0)] (N.gcd 1 0)]]
+reduce [[[(N.div 2 0) : N.--(N.div 1 0)] (N.gcd 1 0)]] ⧗ Number → Number → Rational
add' &[[&[[reduce p q]]]]
- p N.add (N.mul 3 N.++0) (N.mul 1 N.++2)
+ p N.add (N.mul 3 N.++0) (N.mul N.++2 1)
q N.mul N.++0 N.++2
# subtracts two rational numbers
sub &[[&[[p : q]]]] ⧗ Rational → Rational → Rational
- p N.sub (N.mul 3 N.++0) (N.mul 1 N.++2)
+ p N.sub (N.mul 3 N.++0) (N.mul N.++2 1)
q N.add (N.mul 2 0) (N.add 2 0)
…-… sub
@@ -98,10 +127,6 @@ 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
@@ -112,6 +137,11 @@ dec \sub (+1.0) ⧗ Rational → Rational
--‣ dec
+# approximates a rational number to n digits
+approximate &[[[&[[int : float]] (N.quot-rem 2 N.++1)]]] ⧗ Rational → Number → (List Number)
+ int 1
+ float N.number→list (N.div (N.mul 0 (N.pow (+10) 2)) N.++3)
+
# TODO: Regression? Importing this into . won't find Q.eq? anymore
:import std/List L
diff --git a/std/Math/Real.bruijn b/std/Math/Real.bruijn
index 9a4b1bd..d334117 100644
--- a/std/Math/Real.bruijn
+++ b/std/Math/Real.bruijn
@@ -7,7 +7,7 @@
:import std/Math/Rational Q
:import std/Math N
-# a Real is just a Unary → Rational!
+# a Real is just a Number → Rational!
# converts a balanced ternary number to a real number
number→real [[Q.number→rational 1]] ⧗ Number → Real
@@ -18,7 +18,27 @@ number→real [[Q.number→rational 1]] ⧗ Number → Real
approx-eq? [[[Q.eq? (1 2) (0 2)]]] ⧗ Number → Real → Real → Boolean
# TODO: bigger value??
-…≈?… approx-eq? (+100u)
+…≈?… approx-eq? (+100)
+
+# returns true if a real number is greater than another
+gt? [[[Q.gt? (1 2) (0 2)]]] ⧗ Number → Real → Real → Boolean
+
+…>?… gt?
+
+# returns true if a real number is less than another
+lt? [[[Q.lt? (1 2) (0 2)]]] ⧗ Number → Real → Real → Boolean
+
+…<?… lt?
+
+# returns true if a real number is positive
+positive? [\(gt? 0) (+0.0r)] ⧗ Number → Real → Boolean
+
+>?‣ positive?
+
+# returns true if a real number is negative
+negative? [\(lt? 0) (+0.0r)] ⧗ Number → Real → Boolean
+
+<?‣ negative?
# adds two real numbers
add φ Q.add ⧗ Real → Real → Real
@@ -93,7 +113,7 @@ dec \sub (+1.0r) ⧗ Real → Real
# 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
+unary-exp [[0 &[[[[[[[2 1 0 (Q.add 4 (1 : N.--0)) N.++3]] pow fac]]]]] start [[[[1]]]]]] ⧗ Unary → Real
pow N.mul 6 4
fac N.mul 1 3
start [0 (+1) (+1) (+1.0q) (+1)]
@@ -114,7 +134,7 @@ lim-exp [[pow-n [(N.add 2 1) : N.--1] 0]] ⧗ Number → Real
# 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}
+# 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]
@@ -123,7 +143,8 @@ ln [[[L.nth-iterate &[[[op]]] start 1] (--1 / ++1 0) [[[1]]]]] ⧗ Real → Real
: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)
+derive [[[[((3 (2 + 0)) - (3 2)) / 0] ((+1.0r) / conv) 0]]] ⧗ (Real → Real) → (Real → Real)
+ conv number→real (N.pow (+2) (N.mul (+2) 0))
# power function: real^real
pow [[exp (0 ⋅ (ln 1))]] ⧗ Real → Real → Real
@@ -151,9 +172,9 @@ 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)
+ op [0 N.++5 (Q.add 4 ((N.mul 3 2) : N.--1)) num-pow num-fac denom]
+ num-pow N.mul 3 (+2)
+ num-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
@@ -177,21 +198,31 @@ hypot [[sqrt ((0 ⋅ 0) + (1 ⋅ 1))]] ⧗ Real → Real → Real
ψ -(~φ)
# golden ratio from fibonacci convergence
-φ* [(L.index (L.iterate &[[0 : (N.add 1 0)]] ((+0) : (+1))) 0) [[1 : N.--0]]]
+φ* ++[(L.nth-iterate &[[0 : (N.add 1 0)]] ((+0) : (+1)) 0) [[1 : N.--0]]]
# real fibonacci
fib [((pow φ 0) - (pow ψ 0)) / (sqrt (+5.0r))]
# 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
+atan* [[[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)
+ op [0 ((3 Q.add Q.sub) 4 (Q.div 2 1)) \3 num denom]
+ num 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
+atan [[[fallback] (1 0)]] ⧗ Real → Real
+ normal Q.sub π/2-pm conj-atan
+ π/2-pm Q.mul (Q.>?0 (+1.0q) (-1.0q)) (π/2 1)
+ conj-atan atan* [Q.div (+1.0q) 1] 1
+ fallback Q.lt? Q.|0 (+1.0) (atan* [1] 1) normal
+
+# 2-argument arctan
+atan2 [[[[[go]] (2 0) (1 0)]]] ⧗ Real → Real → Real
+ go Q.add a (Q.mul b (Q.add c d))
+ z (+0.0q)
+ a Q.=?0 z (atan [Q.div 2 1] 2)
+ b Q.sub (+1.0q) (Q.<?1 (+2.0q) z)
+ c Q.<?0 (Ï€ 2) z
+ d Q.=?0 (Ï€/2 2) z