From 008e4021375883610cf1b07e005a4176acadc0de Mon Sep 17 00:00:00 2001 From: Sam Anthony Date: Sat, 29 Jul 2023 11:19:55 -0230 Subject: trig functions --- calc.go | 12 ++++++++++-- func.go | 50 +++++++++++++++++++++++++++++++++++++++++--------- ui.go | 2 +- 3 files changed, 52 insertions(+), 12 deletions(-) diff --git a/calc.go b/calc.go index 8afc43a..1d969cc 100644 --- a/calc.go +++ b/calc.go @@ -5,9 +5,17 @@ import ( "strings" ) +type AngleMode int + +const ( + modeDeg = iota + modeRad +) + type Calculator struct { - stack Stack - buf string + stack Stack + buf string + anglem AngleMode } // swap swaps the values of the buffer and the bottom element of the stack. If diff --git a/func.go b/func.go index 914cb61..445cb41 100644 --- a/func.go +++ b/func.go @@ -1,18 +1,50 @@ package main -import "math" +import ( + "fmt" + "math" +) -// parseFunction returns nil is s is not a valid function. -func parseFunction(s string) func(Stack) { - switch s { - case "sin": - return sin +// parseFunction returns nil is fn is not a valid function. +func parseFunction(fn string) func(Calculator) { + switch fn { + case "sin", "cos", "tan": + return trig(fn) } return nil } -func sin(stack Stack) { - if len(stack) > 0 { - stack[len(stack)-1] = math.Sin(stack[len(stack)-1]) +// trig returns a closure that performs the trig function specified by fn. +// Panics if fn is not one of "sin", "cos" or "tan". +func trig(fn string) func(Calculator) { + return func(c Calculator) { + if len(c.stack) <= 0 { + return + } + v := &c.stack[len(c.stack)-1] + // The math package expects arguments to trig functions to be in radians. + if c.anglem == modeDeg { + *v = radians(*v) + } + switch fn { + case "sin": + *v = math.Sin(*v) + case "cos": + *v = math.Cos(*v) + case "tan": + *v = math.Tan(*v) + default: + panic(fmt.Sprintf("invalid trig function: '%s'", fn)) + } } } + +// radians converts degrees to radians. +func radians(deg float64) float64 { + return deg * math.Pi / 180.0 +} + +// degrees converts radians to degrees. +func degrees(rad float64) float64 { + return rad * 180 / math.Pi +} diff --git a/ui.go b/ui.go index 9bf9caa..877f11b 100644 --- a/ui.go +++ b/ui.go @@ -56,7 +56,7 @@ func (ui UI) Update(msg tea.Msg) (tea.Model, tea.Cmd) { } case "enter": if fn := parseFunction(ui.calc.buf); fn != nil { - fn(ui.calc.stack) + fn(ui.calc) } else if con := parseConstant(ui.calc.buf); con != nil { ui.calc.stack.push(*con) } else if f, err := strconv.ParseFloat(ui.calc.buf, 64); err == nil { -- cgit v1.2.3