commit 239e21509fddc21f28af1d26182099cdc204f296
parent 31339383342de14bcc5030acd3b11439c5d10938
Author: NunoSempere <nuno.semperelh@protonmail.com>
Date: Tue, 18 Jun 2024 22:44:24 -0400
fengshui
Diffstat:
| A | .fermi.go.swp | | | 0 | |
| M | fermi.go | | | 179 | ++++++++++++++++++++++++++++++------------------------------------------------- |
| A | pretty/pretty.go | | | 52 | ++++++++++++++++++++++++++++++++++++++++++++++++++++ |
3 files changed, 120 insertions(+), 111 deletions(-)
diff --git a/.fermi.go.swp b/.fermi.go.swp
Binary files differ.
diff --git a/fermi.go b/fermi.go
@@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"git.nunosempere.com/NunoSempere/fermi/sample"
+ "git.nunosempere.com/NunoSempere/fermi/pretty"
"math"
"os"
"sort"
@@ -39,6 +40,33 @@ type FilledSamples struct {
xs []float64
}
+/* Dist interface functions */
+// https://go.dev/tour/methods/9
+func (p Scalar) Samples() []float64 {
+ xs := make([]float64, N_SAMPLES)
+ for i := 0; i < N_SAMPLES; i++ {
+ xs[i] = float64(p)
+ }
+ return xs
+}
+
+func (ln Lognormal) Samples() []float64 {
+ sampler := func(r sample.Src) float64 { return sample.Sample_to(ln.low, ln.high, r) }
+ // return sample.Sample_parallel(sampler, N_SAMPLES)
+ // Can't do parallel because then I'd have to await throughout the code
+ return sample.Sample_serially(sampler, N_SAMPLES)
+}
+
+func (beta Beta) Samples() []float64 {
+ sampler := func(r sample.Src) float64 { return sample.Sample_beta(beta.a, beta.b, r) }
+ // return sample.Sample_parallel(sampler, N_SAMPLES)
+ return sample.Sample_serially(sampler, N_SAMPLES)
+}
+
+func (fs FilledSamples) Samples() []float64 {
+ return fs.xs
+}
+
/* Constants */
const GENERAL_ERR_MSG = " Operation | Variable assignment | Special\n" +
" Operation: operator operand\n" +
@@ -66,35 +94,44 @@ const NORMAL90CONFIDENCE = 1.6448536269514727
const INIT_DIST Scalar = Scalar(1)
const N_SAMPLES = 100_000
-/* Dist interface functions */
-// https://go.dev/tour/methods/9
-func (p Scalar) Samples() []float64 {
- xs := make([]float64, N_SAMPLES)
- for i := 0; i < N_SAMPLES; i++ {
- xs[i] = float64(p)
+/* Pretty print for distributions */
+// Needs types
+func prettyPrintDist(dist Dist) {
+ switch v := dist.(type) {
+ case Lognormal:
+ fmt.Printf("=> ")
+ pretty.PrettyPrint2Floats(v.low, v.high)
+ case FilledSamples:
+ tmp_xs := make([]float64, N_SAMPLES)
+ copy(tmp_xs, v.xs)
+ sort.Slice(tmp_xs, func(i, j int) bool {
+ return tmp_xs[i] < tmp_xs[j]
+ })
+ low_int := N_SAMPLES / 20
+ low := tmp_xs[low_int]
+ high_int := N_SAMPLES * 19 / 20
+ high := tmp_xs[high_int]
+ fmt.Printf("=> ")
+ pretty.PrettyPrintFloat(low)
+ fmt.Printf(" ")
+ pretty.PrettyPrintFloat(high)
+ fmt.Printf(" (")
+ pretty.PrettyPrintInt(N_SAMPLES)
+ fmt.Printf(" samples)\n")
+ case Beta:
+ fmt.Printf("=> beta ")
+ pretty.PrettyPrint2Floats(v.a, v.b)
+ case Scalar:
+ fmt.Printf("=> scalar ")
+ w := float64(v)
+ pretty.PrettyPrintFloat(w)
+ fmt.Println()
+ default:
+ fmt.Printf("%v", v)
}
- return xs
-}
-
-func (ln Lognormal) Samples() []float64 {
- sampler := func(r sample.Src) float64 { return sample.Sample_to(ln.low, ln.high, r) }
- // return sample.Sample_parallel(sampler, N_SAMPLES)
- // Can't do parallel because then I'd have to await throughout the code
- return sample.Sample_serially(sampler, N_SAMPLES)
-}
-
-func (beta Beta) Samples() []float64 {
- sampler := func(r sample.Src) float64 { return sample.Sample_beta(beta.a, beta.b, r) }
- // return sample.Sample_parallel(sampler, N_SAMPLES)
- return sample.Sample_serially(sampler, N_SAMPLES)
-}
-
-func (fs FilledSamples) Samples() []float64 {
- return fs.xs
}
// Parse line into Distribution
-
func parseLineErr(err_msg string) (string, Dist, error) {
fmt.Println(GENERAL_ERR_MSG)
fmt.Println(err_msg)
@@ -253,8 +290,10 @@ func divideDists(old_dist Dist, new_dist Dist) (Dist, error) {
{
switch n := new_dist.(type) {
case Lognormal:
+ // to do: check division by zero
return multiplyLogDists(o, Lognormal{low: 1.0 / n.high, high: 1.0 / n.low}), nil
case Scalar:
+ // to do: check division by zero
return multiplyLogDists(o, Lognormal{low: 1.0 / float64(n), high: 1.0 / float64(n)}), nil
default:
return operateDistsAsSamples(old_dist, new_dist, "/")
@@ -266,6 +305,7 @@ func divideDists(old_dist Dist, new_dist Dist) (Dist, error) {
case Lognormal:
return multiplyLogDists(Lognormal{low: float64(o), high: float64(o)}, Lognormal{low: 1.0 / n.high, high: 1.0 / n.low}), nil
case Scalar:
+ // to do: check division by zero
return Scalar(float64(o) / float64(n)), nil
default:
return operateDistsAsSamples(old_dist, new_dist, "/")
@@ -276,92 +316,9 @@ func divideDists(old_dist Dist, new_dist Dist) (Dist, error) {
}
}
-/* Pretty print distributions
- */
-func prettyPrintInt(n int) {
- switch {
- case math.Abs(float64(n)) >= 1_000_000_000_000:
- fmt.Printf("%dT", n/1_000_000_000_000)
- case math.Abs(float64(n)) >= 1_000_000_000:
- fmt.Printf("%dB", n/1_000_000_000)
- case math.Abs(float64(n)) >= 1_000_000:
- fmt.Printf("%dM", n/1_000_000)
- case math.Abs(float64(n)) >= 1_000:
- fmt.Printf("%dK", n/1_000)
- default:
- fmt.Printf("%df", n)
- }
-}
-
-func prettyPrintFloat(f float64) {
- switch {
- case math.Abs(f) >= 1_000_000_000_000:
- fmt.Printf("%.1fT", f/1_000_000_000_000)
- case math.Abs(f) >= 1_000_000_000:
- fmt.Printf("%.1fB", f/1_000_000_000)
- case math.Abs(f) >= 1_000_000:
- fmt.Printf("%.1fM", f/1_000_000)
- case math.Abs(f) >= 1_000:
- fmt.Printf("%.1fK", f/1_000)
-
- case math.Abs(f) <= 0.0001:
- fmt.Printf("%.5f", f)
- case math.Abs(f) <= 0.001:
- fmt.Printf("%.4f", f)
- case math.Abs(f) <= 0.01:
- fmt.Printf("%.3f", f)
- case math.Abs(f) <= 0.1:
- fmt.Printf("%.2f", f)
- default:
- fmt.Printf("%.1f", f)
- }
-
-}
-func prettyPrint2Floats(low float64, high float64) {
- prettyPrintFloat(low)
- fmt.Printf(" ")
- prettyPrintFloat(high)
- fmt.Printf("\n")
-}
-
-func prettyPrintDist(dist Dist) {
- switch v := dist.(type) {
- case Lognormal:
- fmt.Printf("=> ")
- prettyPrint2Floats(v.low, v.high)
- case FilledSamples:
- tmp_xs := make([]float64, N_SAMPLES)
- copy(tmp_xs, v.xs)
- sort.Slice(tmp_xs, func(i, j int) bool {
- return tmp_xs[i] < tmp_xs[j]
- })
- low_int := N_SAMPLES / 20
- low := tmp_xs[low_int]
- high_int := N_SAMPLES * 19 / 20
- high := tmp_xs[high_int]
- fmt.Printf("=> ")
- prettyPrintFloat(low)
- fmt.Printf(" ")
- prettyPrintFloat(high)
- fmt.Printf(" (")
- prettyPrintInt(N_SAMPLES)
- fmt.Printf(" samples)\n")
- case Beta:
- fmt.Printf("=> beta ")
- prettyPrint2Floats(v.a, v.b)
- case Scalar:
- fmt.Printf("=> scalar ")
- w := float64(v)
- prettyPrintFloat(w)
- fmt.Println()
- default:
- fmt.Printf("%v", v)
- }
-}
-
/* Combine old dist and new line */
// We want this as a function to be able to have parenthesis/recusion, possibly functions
-func combineStackAndDist(stack Stack, new_dist Dist, op string) Stack {
+func operateStackWithDist(stack Stack, new_dist Dist, op string) Stack {
var combined_dist Dist
var err error
@@ -403,7 +360,7 @@ func runRepl(stack Stack, reader *bufio.Reader) Stack {
/* Parenthesis */
case len(words) == 2 && (words[0] == "*" || words[0] == "+" || words[0] == "-" || words[0] == "/") && words[1] == "(":
new_stack := runRepl(Stack{old_dist: INIT_DIST, vars: stack.vars}, reader)
- stack = combineStackAndDist(stack, new_stack.old_dist, words[0])
+ stack = operateStackWithDist(stack, new_stack.old_dist, words[0])
prettyPrintDist(stack.old_dist)
case len(words) == 1 && words[0] == ")":
return stack
@@ -439,7 +396,7 @@ func runRepl(stack Stack, reader *bufio.Reader) Stack {
if err != nil {
continue replForLoop
}
- stack = combineStackAndDist(stack, new_dist, op)
+ stack = operateStackWithDist(stack, new_dist, op)
prettyPrintDist(stack.old_dist)
}
}
diff --git a/pretty/pretty.go b/pretty/pretty.go
@@ -0,0 +1,52 @@
+package pretty
+
+import (
+ "fmt"
+ "math"
+)
+
+func PrettyPrintInt(n int) {
+ switch {
+ case math.Abs(float64(n)) >= 1_000_000_000_000:
+ fmt.Printf("%dT", n/1_000_000_000_000)
+ case math.Abs(float64(n)) >= 1_000_000_000:
+ fmt.Printf("%dB", n/1_000_000_000)
+ case math.Abs(float64(n)) >= 1_000_000:
+ fmt.Printf("%dM", n/1_000_000)
+ case math.Abs(float64(n)) >= 1_000:
+ fmt.Printf("%dK", n/1_000)
+ default:
+ fmt.Printf("%df", n)
+ }
+}
+
+func PrettyPrintFloat(f float64) {
+ switch {
+ case math.Abs(f) >= 1_000_000_000_000:
+ fmt.Printf("%.1fT", f/1_000_000_000_000)
+ case math.Abs(f) >= 1_000_000_000:
+ fmt.Printf("%.1fB", f/1_000_000_000)
+ case math.Abs(f) >= 1_000_000:
+ fmt.Printf("%.1fM", f/1_000_000)
+ case math.Abs(f) >= 1_000:
+ fmt.Printf("%.1fK", f/1_000)
+
+ case math.Abs(f) <= 0.0001:
+ fmt.Printf("%.5f", f)
+ case math.Abs(f) <= 0.001:
+ fmt.Printf("%.4f", f)
+ case math.Abs(f) <= 0.01:
+ fmt.Printf("%.3f", f)
+ case math.Abs(f) <= 0.1:
+ fmt.Printf("%.2f", f)
+ default:
+ fmt.Printf("%.1f", f)
+ }
+
+}
+func PrettyPrint2Floats(low float64, high float64) {
+ PrettyPrintFloat(low)
+ fmt.Printf(" ")
+ PrettyPrintFloat(high)
+ fmt.Printf("\n")
+}