github.com/cowsed/Parser@v0.0.0-20211216032244-48b10019d380/Elements.go (about) 1 package parser 2 3 import ( 4 "fmt" 5 "math" 6 ) 7 8 //Expression is the simplest possible part of an mathematical expression 9 type Expression interface { 10 Evaluate(vars map[string]float64) float64 11 String() string 12 Latex() string 13 Compile(mm *MemoryManager) int 14 Derive(wrt string) Expression 15 Simplify() Expression 16 } 17 18 //Siner takes the sine of its value 19 type Siner struct { 20 A Expression 21 } 22 23 //Derive takes the derivative of the sin(A) with respect to wrt 24 func (s Siner) Derive(wrt string) Expression { 25 26 return Multiplier{ 27 A: Coser{s.A}, 28 B: s.A.Derive(wrt), 29 } 30 } 31 32 //Evaluate evaluates sin of A 33 func (s Siner) Evaluate(vars map[string]float64) float64 { 34 return math.Sin(s.A.Evaluate(vars)) 35 } 36 37 //String returns a string representation of sin(a) 38 func (s Siner) String() string { 39 return "sin(" + s.A.String() + ")" 40 } 41 42 //Latex returns the latex representation of sin(a) 43 func (s Siner) Latex() string { 44 return "sin(" + s.A.Latex() + ")" 45 } 46 47 //Compile compiles sin into bytecode 48 func (s Siner) Compile(mm *MemoryManager) int { 49 aResult := s.A.Compile(mm) 50 myResultIndex := mm.GetResultSpace() 51 mm.AddBytecode([]Bytecode{SinBytecode, Bytecode(aResult), Bytecode(myResultIndex)}) 52 return myResultIndex 53 } 54 55 //Coser takes the cosine of its value 56 type Coser struct { 57 A Expression 58 } 59 60 //Derive takes the derivative of the cos(A) with respect to wrt 61 func (c Coser) Derive(wrt string) Expression { 62 return Multiplier{ 63 A: Multiplier{ 64 A: Constant{ 65 Value: -1, 66 }, 67 B: Siner{ 68 A: c.A, 69 }, 70 }, 71 B: c.A.Derive(wrt), 72 } 73 } 74 75 //Evaluate evaluates cosine(a) 76 func (c Coser) Evaluate(vars map[string]float64) float64 { 77 return math.Cos(c.A.Evaluate(vars)) 78 } 79 80 //String returns a string representation of cos(a) 81 func (c Coser) String() string { 82 return "cos(" + c.A.String() + ")" 83 } 84 85 //Latex returns a latex representation of cos(a) 86 func (c Coser) Latex() string { 87 return "cos(" + c.A.Latex() + ")" 88 } 89 90 //Compile compiles cos(a) to bytecode 91 func (c Coser) Compile(mm *MemoryManager) int { 92 aResult := c.A.Compile(mm) 93 myResultIndex := mm.GetResultSpace() 94 mm.AddBytecode([]Bytecode{CosBytecode, Bytecode(aResult), Bytecode(myResultIndex)}) 95 return myResultIndex 96 } 97 98 //Adder adds its two parameters 99 type Adder struct { 100 A, B Expression 101 } 102 103 //Derive takes the derivative of A + B. 104 func (a Adder) Derive(wrt string) Expression { 105 return Adder{ 106 A: a.A.Derive(wrt), 107 B: a.B.Derive(wrt), 108 }.Simplify() 109 } 110 111 //Evaluate evaluates a+b 112 func (a Adder) Evaluate(vars map[string]float64) float64 { 113 return a.A.Evaluate(vars) + a.B.Evaluate(vars) 114 } 115 116 //Compile compiles A+B to bytecode 117 func (a Adder) Compile(mm *MemoryManager) int { 118 //Add instructions to memory manager as well as index to result 119 aResult := a.A.Compile(mm) 120 bResult := a.B.Compile(mm) 121 myResultIndex := mm.GetResultSpace() 122 mm.AddBytecode([]Bytecode{AddBytecode, Bytecode(aResult), Bytecode(bResult), Bytecode(myResultIndex)}) 123 return myResultIndex 124 } 125 126 //String returns a string representation of A+B 127 func (a Adder) String() string { 128 return "(" + a.A.String() + " + " + a.B.String() + ")" 129 } 130 131 //Latex returns a latex representation of A+B 132 func (a Adder) Latex() string { 133 return a.A.Latex() + " + " + a.B.Latex() 134 } 135 136 //Subtractor subtracts its two parameters 137 type Subtractor struct { 138 A, B Expression 139 } 140 141 //Derive takes the derivative of A - B. 142 func (s Subtractor) Derive(wrt string) Expression { 143 return Subtractor{ 144 A: s.A.Derive(wrt), 145 B: s.B.Derive(wrt), 146 }.Simplify() 147 } 148 149 //Evaluate evaluates A-B 150 func (s Subtractor) Evaluate(vars map[string]float64) float64 { 151 return s.A.Evaluate(vars) - s.B.Evaluate(vars) 152 } 153 154 //String returns a string representation of A-B 155 func (s Subtractor) String() string { 156 return "(" + s.A.String() + " - " + s.B.String() + ")" 157 } 158 159 //Latex returns a latex representation of A-B 160 func (s Subtractor) Latex() string { 161 return s.A.Latex() + " - " + s.B.Latex() 162 } 163 164 //Compile compiles A-B to bytecode 165 func (s Subtractor) Compile(mm *MemoryManager) int { 166 aResult := s.A.Compile(mm) 167 bResult := s.B.Compile(mm) 168 myResultIndex := mm.GetResultSpace() 169 mm.AddBytecode([]Bytecode{SubBytecode, Bytecode(aResult), Bytecode(bResult), Bytecode(myResultIndex)}) 170 return myResultIndex 171 } 172 173 //Multiplier multiplies its two parameters 174 type Multiplier struct { 175 A, B Expression 176 } 177 178 //Derive takes the derivative of A * B. 179 func (m Multiplier) Derive(wrt string) Expression { 180 return Adder{ 181 A: Multiplier{ 182 A: m.A, 183 B: m.B.Derive(wrt), 184 }, 185 B: Multiplier{ 186 A: m.A.Derive(wrt), 187 B: m.A, 188 }, 189 }.Simplify() 190 } 191 192 //Evaluate evaluates A*B 193 func (m Multiplier) Evaluate(vars map[string]float64) float64 { 194 return m.A.Evaluate(vars) * m.B.Evaluate(vars) 195 } 196 197 //String returns a string representation of A*B 198 func (m Multiplier) String() string { 199 return "(" + m.A.String() + " * " + m.B.String() + ")" 200 } 201 202 //Latex returns a latex representation of A*B 203 func (m Multiplier) Latex() string { 204 return m.A.Latex() + " \\times " + m.B.Latex() 205 } 206 207 //Compile compiles A*B to bytecode 208 func (m Multiplier) Compile(mm *MemoryManager) int { 209 aResult := m.A.Compile(mm) 210 bResult := m.B.Compile(mm) 211 myResultIndex := mm.GetResultSpace() 212 mm.AddBytecode([]Bytecode{MulBytecode, Bytecode(aResult), Bytecode(bResult), Bytecode(myResultIndex)}) 213 return myResultIndex 214 } 215 216 //Divider divides its parameters 217 type Divider struct { 218 A, B Expression 219 } 220 221 //Derive takes the derivative of A / B. 222 func (d Divider) Derive(wrt string) Expression { 223 return Divider{ 224 A: Subtractor{ 225 A: Multiplier{ 226 A: d.B, 227 B: d.A.Derive(wrt), 228 }, 229 B: Multiplier{ 230 A: d.A, 231 B: d.B.Derive(wrt), 232 }, 233 }, 234 B: Powerer{ 235 Base: d.B, 236 Exponent: Constant{2}, 237 }, 238 }.Simplify() 239 } 240 241 //Evaluate evaluates A/B 242 func (d Divider) Evaluate(vars map[string]float64) float64 { 243 return d.A.Evaluate(vars) / d.B.Evaluate(vars) 244 } 245 246 //String returns a string representation of A/B 247 func (d Divider) String() string { 248 return "(" + d.A.String() + " / " + d.B.String() + ")" 249 } 250 251 //Latex returns a latex representation of A/B 252 func (d Divider) Latex() string { 253 return "\\frac{" + d.A.Latex() + "}{" + d.B.Latex() + "}" 254 } 255 256 //Compile compiles A/B to bytecode 257 func (d Divider) Compile(mm *MemoryManager) int { 258 aResult := d.A.Compile(mm) 259 bResult := d.B.Compile(mm) 260 myResultIndex := mm.GetResultSpace() 261 mm.AddBytecode([]Bytecode{DivBytecode, Bytecode(aResult), Bytecode(bResult), Bytecode(myResultIndex)}) 262 return myResultIndex 263 } 264 265 //NaturalLogger takes the natural log of A 266 type NaturalLogger struct { 267 A Expression 268 } 269 270 //Evaluate evaluates ln(A) 271 func (n NaturalLogger) Evaluate(vars map[string]float64) float64 { 272 return math.Log(n.A.Evaluate(vars)) 273 } 274 275 //Derive takes the derivative of ln(A). 276 func (n NaturalLogger) Derive(wrt string) Expression { 277 return Multiplier{ 278 A: Divider{ 279 A: Constant{1}, 280 B: n.A, 281 }, 282 B: n.A.Derive(wrt), 283 }.Simplify() 284 } 285 286 //Compile compiles ln(A) to bytecode 287 func (n NaturalLogger) Compile(mm *MemoryManager) int { 288 aResult := n.A.Compile(mm) 289 myResultIndex := mm.GetResultSpace() 290 mm.AddBytecode([]Bytecode{LNBytecode, Bytecode(aResult), Bytecode(myResultIndex)}) 291 return myResultIndex 292 } 293 294 //Latex returns the latex representation of ln(a) 295 func (n NaturalLogger) Latex() string { 296 return fmt.Sprintf("\\ln{%s}", n.A.Latex()) 297 } 298 299 //String returns the string representation of ln(a) 300 func (n NaturalLogger) String() string { 301 return fmt.Sprintf("ln(%s)", n.A.String()) 302 } 303 304 //Powerer raises base to exponent 305 type Powerer struct { 306 Base, Exponent Expression 307 } 308 309 //Derive takes the derivative of A^B 310 //https://www.youtube.com/watch?v=SUxcFxM65Ho 311 func (p Powerer) Derive(wrt string) Expression { 312 return Multiplier{ 313 A: Powerer{ 314 Base: p.Base, 315 Exponent: p.Exponent, 316 }, 317 B: Adder{ 318 A: Divider{ 319 A: Multiplier{ 320 A: p.Exponent, 321 B: p.Base.Derive(wrt), 322 }, 323 B: p.Base, 324 }, 325 B: Multiplier{ 326 A: p.Exponent.Derive(wrt), 327 B: NaturalLogger{ 328 A: p.Base, 329 }, 330 }, 331 }, 332 }.Simplify() 333 } 334 335 //Evaluate evaluates base^power 336 func (p Powerer) Evaluate(vars map[string]float64) float64 { 337 return math.Pow(p.Base.Evaluate(vars), p.Exponent.Evaluate(vars)) 338 } 339 340 //String returns a string representation of base^exponent 341 func (p Powerer) String() string { 342 return "(" + p.Base.String() + " ^ " + p.Exponent.String() + ")" 343 } 344 345 //Latex returns a latex representation of base^exponent 346 func (p Powerer) Latex() string { 347 return p.Base.Latex() + "^{" + p.Exponent.Latex() + "}" 348 } 349 350 //Compile compiles it to bytecode 351 func (p Powerer) Compile(mm *MemoryManager) int { 352 aResult := p.Base.Compile(mm) 353 bResult := p.Exponent.Compile(mm) 354 myResultIndex := mm.GetResultSpace() 355 mm.AddBytecode([]Bytecode{PowBytecode, Bytecode(aResult), Bytecode(bResult), Bytecode(myResultIndex)}) 356 return myResultIndex 357 } 358 359 //Constant holds a numeric constant 360 type Constant struct { 361 Value float64 362 } 363 364 //Derive takes the derivative of a constant (0) 365 func (c Constant) Derive(wrt string) Expression { 366 return Constant{0} 367 } 368 369 //String returns the string representation of the number 370 func (c Constant) String() string { 371 return fmt.Sprintf("%g", c.Value) 372 } 373 374 //Latex returns the latex representation of the number 375 func (c Constant) Latex() string { 376 return fmt.Sprintf("%g", c.Value) 377 } 378 379 //Evaluate returns the value of the constant 380 func (c Constant) Evaluate(vars map[string]float64) float64 { 381 return c.Value 382 } 383 384 //Compile creates a place to store the constant 385 func (c Constant) Compile(mm *MemoryManager) int { 386 i := mm.AddConstant(c.Value) 387 return i 388 } 389 390 //Variable holds a variable in an equation 391 type Variable struct { 392 Symbol string 393 } 394 395 //String returns the string representation of the variable 396 func (v Variable) String() string { 397 return v.Symbol 398 } 399 400 //Latex returns the latex representation of the variable 401 func (v Variable) Latex() string { 402 return v.Symbol 403 } 404 405 //Evaluate takes the variable and looks up its numeric value at the time of evaluation 406 func (v Variable) Evaluate(vars map[string]float64) float64 { 407 return vars[v.Symbol] 408 } 409 410 //Compile creates a space for the variable to stay and records where they go to fill in later 411 func (v Variable) Compile(mm *MemoryManager) int { 412 i := mm.AddVariable(v.Symbol) 413 return i 414 } 415 416 //Derive takes the derivative of the variable 417 func (v Variable) Derive(wrt string) Expression { 418 if v.Symbol == wrt { 419 return Constant{1} 420 } 421 //Not with respect to this variable. Variable is basically constant 422 return Constant{0} 423 424 }