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  }