home *** CD-ROM | disk | FTP | other *** search
/ PC Users 1998 June / Cd Pc Users 9.iso / prog / inst / baslibs / clsequat.cls < prev    next >
Encoding:
Text File  |  1997-01-01  |  20.5 KB  |  784 lines

  1. VERSION 1.0 CLASS
  2. BEGIN
  3.   MultiUse = -1  'True
  4. END
  5. Attribute VB_Name = "clsEquation"
  6. Attribute VB_Creatable = False
  7. Attribute VB_Exposed = False
  8. Option Explicit
  9.  
  10. ' An equation solver class.
  11. ' Probably not really quick, but it's all VBasic code.
  12. '
  13. ' It does a significant amount of work in the
  14. ' parsing of an equation, so it's more efficient
  15. ' when solving the same equation several times.
  16. '
  17. ' The equation is not case sensitive.
  18. '
  19. '
  20. ' 1-1-96: A Bug related to determining the difference between
  21. '         a negative sign and negation was fixed. (And a priority
  22. '         level PRI_NEG was added.)  - TPA
  23. '
  24.  
  25. Private Dirty As Boolean
  26. Private Parsed As Boolean
  27.  
  28. Private Vars As New Collection
  29. Private Equ As String
  30. Private Deg As Boolean
  31.  
  32. Private dAnswer As Double
  33. Private EquParsed As Collection   'The parsed equation
  34. Private EquOrder  As Collection   'Order in which to solve the equation
  35.  
  36.  
  37. ' Constants used in parsing
  38. ' Priority levels
  39. Private Const PRI_ADD = 1
  40. Private Const PRI_MOD = 2
  41. Private Const PRI_MUL = 3
  42. Private Const PRI_NEG = 4
  43. Private Const PRI_EXP = 5
  44. Private Const PRI_VAR = 6
  45. Private Const PRI_PAR = 7
  46. Private Const PRI_LEVEL = 7
  47.  
  48. Private Const EQ_NONE = 0
  49. Private Const EQ_STRING = 1
  50. Private Const EQ_NUMBER = 2
  51.  
  52. '
  53. Private Const ER_NONE = 0
  54. Private Const ER_VAR = 1
  55.  
  56.  
  57. Private Const PI = 3.14159265358979
  58. Private Const DEG_TO_RAD = 0.01745329251995
  59. Private Const RAD_TO_DEG = 57.2957795131
  60.  
  61. Public Property Let Degrees(b As Boolean)
  62.    If b <> Deg Then
  63.       Deg = b
  64.       Dirty = True
  65.    End If
  66. End Property
  67.  
  68.  
  69. Public Property Get Degrees() As Boolean
  70.    Degrees = Deg
  71. End Property
  72.  
  73.  
  74.  
  75.  
  76.  
  77.  
  78.  
  79. Private Function GetRight(ByVal j As Long, v() As Variant) As Long
  80.    Dim i As Long
  81.    
  82.    For i = j + 1 To UBound(v)
  83.       If Not IsNull(v(i)) Then
  84.          GetRight = i
  85.          Exit Function
  86.       End If
  87.    Next i
  88.    GetRight = 0
  89. End Function
  90.  
  91. Private Function GetLeft(ByVal j As Long, v() As Variant) As Long
  92.    Dim i As Long
  93.    
  94.    For i = j - 1 To 1 Step -1
  95.       If Not IsNull(v(i)) Then
  96.          GetLeft = i
  97.          Exit Function
  98.       End If
  99.    Next i
  100.    GetLeft = 0
  101. End Function
  102. Public Sub VarClear()
  103.    Set Vars = New Collection
  104.    Dirty = True
  105. End Sub
  106.  
  107.  
  108. Public Property Let Equation(e As String)
  109.    Parsed = False
  110.    Dirty = True
  111.    Equ = LCase(e)
  112. End Property
  113.  
  114. Public Property Get Equation() As String
  115.    Equation = Equ
  116. End Property
  117.  
  118.  
  119. Private Sub Parse()
  120.    Dim i As Integer
  121.    Dim s As String
  122.    Dim t As Integer
  123.    Dim j As Integer
  124.    Dim sTmp As String
  125.    Dim p As Integer
  126.    Dim EquPriority As New Collection
  127.    Dim maxPriority
  128.    Dim isNeg As Boolean
  129.    
  130.    s = ""
  131.    t = EQ_NONE
  132.    j = 1
  133.    p = 0
  134.    isNeg = False
  135.    Set EquParsed = New Collection
  136.    
  137.    EquParsed.Add ""
  138.    EquPriority.Add ""
  139.    maxPriority = PRI_LEVEL
  140.    
  141.    For i = 1 To Len(Equ)
  142.       sTmp = Mid$(Equ, i, 1)
  143.       
  144.       Select Case sTmp
  145.       Case "A" To "Z", "a" To "z", "_"
  146.          If t = EQ_NONE Then
  147.             t = EQ_STRING
  148.             s = sTmp
  149.          ElseIf t = EQ_NUMBER Then
  150.             t = EQ_STRING
  151.             EquParsed.Add s, , j
  152.             EquPriority.Add 0, , j
  153.             j = j + 1
  154.             EquParsed.Add "*", , j
  155.             EquPriority.Add PRI_MUL + p, , j
  156.             j = j + 1
  157.             s = sTmp
  158.          Else
  159.             s = s + sTmp
  160.          End If
  161.          isNeg = True
  162.          
  163.       Case "1" To "9", "0", "."
  164.          If t = EQ_NONE Then
  165.             t = EQ_NUMBER
  166.             s = sTmp
  167.          Else
  168.             s = s + sTmp
  169.          End If
  170.          isNeg = True
  171.       
  172.       Case "(":
  173.          If t = EQ_STRING Then
  174.             EquParsed.Add s + sTmp, , j
  175.             EquPriority.Add p + PRI_PAR, , j
  176.             j = j + 1
  177.             s = ""
  178.          ElseIf t = EQ_NUMBER Then
  179.             EquParsed.Add s, , j
  180.             EquPriority.Add 0, , j
  181.             j = j + 1
  182.             EquParsed.Add "*", , j
  183.             EquPriority.Add p + PRI_MUL, , j
  184.             j = j + 1
  185.             EquParsed.Add sTmp, , j
  186.             EquPriority.Add p + PRI_PAR, , j
  187.             j = j + 1
  188.             s = ""
  189.          Else
  190.             EquParsed.Add sTmp, , j
  191.             EquPriority.Add p + PRI_PAR, , j
  192.             j = j + 1
  193.          End If
  194.          
  195.          p = p + PRI_LEVEL
  196.          t = EQ_NONE
  197.          
  198.          If maxPriority < p + PRI_LEVEL Then
  199.             maxPriority = p + PRI_LEVEL
  200.          End If
  201.          isNeg = False
  202.       
  203.       Case "*", "/":
  204.          If t <> EQ_NONE Then
  205.             EquParsed.Add s, , j
  206.             EquPriority.Add IIf(t = EQ_STRING, p + PRI_VAR, 0), , j
  207.             j = j + 1
  208.             s = ""
  209.          End If
  210.          
  211.          EquParsed.Add sTmp, , j
  212.          EquPriority.Add p + PRI_MUL, , j
  213.          j = j + 1
  214.          t = EQ_NONE
  215.          isNeg = False
  216.       
  217.       Case "\":
  218.          If t <> EQ_NONE Then
  219.             EquParsed.Add s, , j
  220.             EquPriority.Add IIf(t = EQ_STRING, p + PRI_VAR, 0), , j
  221.             j = j + 1
  222.             s = ""
  223.          End If
  224.          
  225.          EquParsed.Add sTmp, , j
  226.          EquPriority.Add p + PRI_MUL, , j
  227.          j = j + 1
  228.          t = EQ_NONE
  229.          isNeg = False
  230.       
  231.       Case "+":
  232.          If t <> EQ_NONE Then
  233.             EquParsed.Add s, , j
  234.             EquPriority.Add IIf(t = EQ_STRING, p + PRI_VAR, 0), , j
  235.             j = j + 1
  236.             s = ""
  237.             EquParsed.Add sTmp, , j
  238.             EquPriority.Add p + PRI_ADD, , j
  239.             j = j + 1
  240.             t = EQ_NONE
  241.          Else
  242.             'Ignore things like "(+1)"
  243.          End If
  244.          isNeg = False
  245.       
  246.       Case "-":
  247.          If t <> EQ_NONE Then
  248.             EquParsed.Add s, , j
  249.             EquPriority.Add IIf(t = EQ_STRING, p + PRI_VAR, 0), , j
  250.             j = j + 1
  251.             s = ""
  252.          End If
  253.          
  254.          If isNeg Then
  255.             EquParsed.Add sTmp, , j
  256.             EquPriority.Add p + PRI_ADD, , j
  257.             j = j + 1
  258.             t = EQ_NONE
  259.          Else
  260.             EquParsed.Add "~", , j
  261.             EquPriority.Add p + PRI_NEG, , j
  262.             j = j + 1
  263.             t = EQ_NONE
  264.          End If
  265.          
  266.          isNeg = False
  267.          
  268.       Case "^":
  269.          If t <> EQ_NONE Then
  270.             EquParsed.Add s, , j
  271.             EquPriority.Add IIf(t = EQ_STRING, p + PRI_VAR, 0), , j
  272.             j = j + 1
  273.             s = ""
  274.          End If
  275.          
  276.          EquParsed.Add sTmp, , j
  277.          EquPriority.Add p + PRI_EXP, , j
  278.          j = j + 1
  279.          t = EQ_NONE
  280.          isNeg = False
  281.          
  282.       Case "%":
  283.          If t <> EQ_NONE Then
  284.             EquParsed.Add s, , j
  285.             EquPriority.Add IIf(t = EQ_STRING, p + PRI_VAR, 0), , j
  286.             j = j + 1
  287.             s = ""
  288.          End If
  289.          
  290.          EquParsed.Add sTmp, , j
  291.          EquPriority.Add p + PRI_MOD, , j
  292.          j = j + 1
  293.          t = EQ_NONE
  294.          isNeg = False
  295.          
  296.       Case ",":
  297.          If t <> EQ_NONE Then
  298.             EquParsed.Add s, , j
  299.             EquPriority.Add IIf(t = EQ_STRING, p + PRI_VAR, 0), , j
  300.             j = j + 1
  301.             s = ""
  302.          End If
  303.          
  304.          EquParsed.Add Null, , j
  305.          EquPriority.Add 0, , j
  306.          j = j + 1
  307.          t = EQ_NONE
  308.          isNeg = False
  309.  
  310.       Case ")":
  311.          If t <> EQ_NONE Then
  312.             EquParsed.Add s, , j
  313.             EquPriority.Add IIf(t = EQ_STRING, p + PRI_VAR, 0), , j
  314.             j = j + 1
  315.             s = ""
  316.          End If
  317.          
  318.          EquParsed.Add sTmp, , j
  319.          EquPriority.Add p - (PRI_LEVEL - PRI_PAR), , j
  320.          p = p - PRI_LEVEL
  321.          j = j + 1
  322.          t = EQ_NONE
  323.          isNeg = True
  324.       End Select
  325.    Next i
  326.    
  327.    If s <> "" Then
  328.       EquParsed.Add s, , j
  329.       EquPriority.Add IIf(t = EQ_STRING, p + PRI_VAR, 0), , j
  330.       j = j + 1
  331.    End If
  332.    
  333.    EquParsed.Remove j
  334.    EquPriority.Remove j
  335.    
  336.    If p <> 0 Then
  337.       Err.Raise EQ_PAREN, "clsEquation", "Unbalanced parenthesis"
  338.       Exit Sub
  339.    End If
  340.    
  341.       ' Debugging section...
  342.       'For i = 1 To EquParsed.Count
  343.       '   Debug.Print EquParsed(i) & ";";
  344.       'Next i
  345.       'Debug.Print
  346.       '   For i = 1 To EquPriority.Count
  347.       '   Debug.Print EquPriority(i) & ";";
  348.       'Next i
  349.       'Debug.Print
  350.       'Debug.Print "MaxPriority = " & maxPriority
  351.       ' End Debugging section....
  352.    
  353.    Set EquOrder = New Collection
  354.    EquOrder.Add ""
  355.    
  356.    For j = 1 To maxPriority
  357.       For i = EquPriority.Count To 1 Step -1
  358.          If EquPriority(i) = j Then
  359.             EquOrder.Add i, , , 1
  360.          End If
  361.       Next i
  362.    Next j
  363.    
  364.    EquOrder.Remove 1
  365.    
  366.    'For i = 1 To EquOrder.Count
  367.    '   Debug.Print EquOrder(i) & ";";
  368.    'Next i
  369.    'Debug.Print
  370.    
  371.    Parsed = True
  372. End Sub
  373. Public Sub VarRemove(Name As String)
  374.    On Error Resume Next
  375.    Vars.Remove Name
  376.    Dirty = True
  377. End Sub
  378.  
  379. Public Function Solution() As Double
  380.    If Dirty Then
  381.       Solve
  382.    End If
  383.    
  384.    Solution = dAnswer
  385. End Function
  386.  
  387. Public Sub Solve()
  388.    Dim i As Long
  389.    Dim j As Long
  390.    Dim l As Long
  391.    Dim r As Long
  392.    Dim m As Long
  393.    Dim N As Long
  394.    Dim X As Double
  395.    Dim Y As Double
  396.    Dim v As Variant
  397.    Dim eSpace As Integer
  398.    Dim Temp() As Variant
  399.    Dim f As clsEquation
  400.    Dim j2 As Long  ' debug variable
  401.    
  402.    On Error GoTo SolveError
  403.    
  404.    If Not Parsed Then
  405.        Parse
  406.    End If
  407.       
  408.    ' Copy the equation to a working array
  409.    ReDim Temp(1 To EquParsed.Count)
  410.    
  411.    For i = 1 To EquParsed.Count
  412.       Temp(i) = EquParsed(i)
  413.    Next
  414.    
  415.    eSpace = ER_NONE
  416.    
  417.    ' Solve the equation
  418.    For i = 1 To EquOrder.Count
  419.       'Debug.Print "Pro -> " & EquOrder(i) & " = ";
  420.       'For j2 = 1 To UBound(Temp)
  421.       '   Debug.Print Temp(j2) & ";";
  422.       'Next j2
  423.       'Debug.Print
  424.       
  425.       m = EquOrder(i)
  426.       v = Temp(m)
  427.       
  428.       Select Case v
  429.       ' Standard operators
  430.       Case "~"  'Negative operator (inserted by the parser)
  431.          r = GetRight(m, Temp)
  432.          Temp(m) = -CDbl(Temp(r))
  433.          Temp(r) = Null
  434.          
  435.       Case "*"
  436.          l = GetLeft(m, Temp)
  437.          r = GetRight(m, Temp)
  438.          Temp(l) = CDbl(Temp(l)) * CDbl(Temp(r))
  439.          Temp(r) = Null
  440.          Temp(m) = Null
  441.          
  442.       Case "/"
  443.          l = GetLeft(m, Temp)
  444.          r = GetRight(m, Temp)
  445.          Temp(l) = CDbl(Temp(l)) / CDbl(Temp(r))
  446.          Temp(r) = Null
  447.          Temp(m) = Null
  448.          
  449.       Case "\"
  450.          l = GetLeft(m, Temp)
  451.          r = GetRight(m, Temp)
  452.          Temp(l) = CDbl(Temp(l)) \ CDbl(Temp(r))
  453.          Temp(r) = Null
  454.          Temp(m) = Null
  455.          
  456.       Case "+"
  457.          l = GetLeft(m, Temp)
  458.          r = GetRight(m, Temp)
  459.          Temp(l) = CDbl(Temp(l)) + CDbl(Temp(r))
  460.          Temp(r) = Null
  461.          Temp(m) = Null
  462.     
  463.       Case "-"
  464.          l = GetLeft(m, Temp)
  465.          r = GetRight(m, Temp)
  466.          Temp(l) = CDbl(Temp(l)) - CDbl(Temp(r))
  467.          Temp(r) = Null
  468.          Temp(m) = Null
  469.     
  470.       Case "^"
  471.          l = GetLeft(m, Temp)
  472.          r = GetRight(m, Temp)
  473.          Temp(l) = CDbl(Temp(l)) ^ CDbl(Temp(r))
  474.          Temp(r) = Null
  475.          Temp(m) = Null
  476.          
  477.       Case "%"
  478.          l = GetLeft(m, Temp)
  479.          r = GetRight(m, Temp)
  480.          Temp(l) = CDbl(Temp(l)) Mod CDbl(Temp(r))
  481.          Temp(r) = Null
  482.          Temp(m) = Null
  483.          
  484.       Case "("
  485.          i = i + 1
  486.          N = EquOrder(i)
  487.          r = GetRight(m, Temp)
  488.          If r >= N Then
  489.             Temp(m) = 0#
  490.             Temp(N) = Null
  491.          Else
  492.             Temp(m) = Temp(r)
  493.             Temp(r) = Null
  494.             Temp(N) = Null
  495.          End If
  496.      
  497.       Case Else
  498.          If Right$(Temp(m), 1) = "(" Then
  499.             'Must be a function
  500.             i = i + 1
  501.             N = EquOrder(i)
  502.             
  503.             l = GetRight(m, Temp)
  504.             r = GetLeft(N, Temp)
  505.             
  506.             If l >= N Then
  507.                Err.Raise EQ_ARGS, "clsEquation", "Invalid arguments to function: " & v & ")"
  508.                Exit Sub
  509.             Else
  510.                X = CDbl(Temp(l))
  511.             End If
  512.             
  513.             If r <= m Then
  514.                Err.Raise EQ_ARGS, "clsEquation", "Invalid arguments to function: " & v & ")"
  515.                Exit Sub
  516.             Else
  517.                Y = CDbl(Temp(r))
  518.             End If
  519.             
  520.             Temp(r) = Null
  521.             Temp(l) = Null
  522.             Temp(m) = Null
  523.             Temp(N) = Null
  524.             
  525.             Select Case v
  526.                ' Standard functions
  527.                Case "abs("
  528.                   Temp(m) = Abs(X)
  529.                   
  530.                Case "atn("
  531.                   If Degrees Then
  532.                      Temp(m) = Atn(X) * RAD_TO_DEG
  533.                   Else
  534.                      Temp(m) = Atn(X)
  535.                   End If
  536.                   
  537.                Case "arctan("
  538.                   If Degrees Then
  539.                      Temp(m) = Atn(X) * RAD_TO_DEG
  540.                   Else
  541.                      Temp(m) = Atn(X)
  542.                   End If
  543.                   
  544.                Case "cos("
  545.                   If Degrees Then
  546.                      Temp(m) = Cos(X * DEG_TO_RAD)
  547.                   Else
  548.                      Temp(m) = Cos(X)
  549.                   End If
  550.                   
  551.                Case "exp("
  552.                   Temp(m) = Exp(X)
  553.                   
  554.                Case "fix("
  555.                   Temp(m) = Fix(X)
  556.                   
  557.                Case "int("
  558.                   Temp(m) = Int(X)
  559.                   
  560.                Case "log("
  561.                   Temp(m) = Log(X)
  562.                   
  563.                Case "rnd("
  564.                   Temp(m) = Rnd(X)
  565.                   
  566.                Case "sgn("
  567.                   Temp(m) = Sgn(X)
  568.                   
  569.                Case "sin("
  570.                   If Degrees Then
  571.                      Temp(m) = Sin(X * DEG_TO_RAD)
  572.                   Else
  573.                      Temp(m) = Sin(X)
  574.                   End If
  575.                   
  576.                Case "sqr("
  577.                   Temp(m) = Sqr(X)
  578.                   
  579.                Case "tan("
  580.                   If Degrees Then
  581.                      Temp(m) = Tan(X * DEG_TO_RAD)
  582.                   Else
  583.                      Temp(m) = Tan(X)
  584.                   End If
  585.                   
  586.                ' 2 variable functions
  587.                Case "min("
  588.                   Temp(m) = IIf(X < Y, X, Y)
  589.                   
  590.                Case "max("
  591.                   Temp(m) = IIf(X > Y, X, Y)
  592.                   
  593.                Case "random("
  594.                   Temp(m) = (Rnd * (Y - X)) + X
  595.                   
  596.                Case "mod("
  597.                   Temp(m) = X Mod Y
  598.                   
  599.                Case "logn("
  600.                   Temp(m) = Log(X) / Log(Y)
  601.                
  602.                ' Misc equations
  603.                Case "rand("
  604.                   Temp(m) = Int(Rnd * X)
  605.                
  606.                ' Derived functions
  607.                Case "sec("
  608.                   If Degrees Then
  609.                      Temp(m) = (1 / Cos(X * DEG_TO_RAD))
  610.                   Else
  611.                      Temp(m) = 1 / Cos(X)
  612.                   End If
  613.                   
  614.                Case "cosec("
  615.                   If Degrees Then
  616.                      Temp(m) = (1 / Sin(X * DEG_TO_RAD))
  617.                   Else
  618.                      Temp(m) = 1 / Sin(X)
  619.                   End If
  620.                   
  621.                Case "cotan("
  622.                   If Degrees Then
  623.                      Temp(m) = (1 / Tan(X * DEG_TO_RAD))
  624.                   Else
  625.                      Temp(m) = 1 / Tan(X)
  626.                   End If
  627.                   
  628.                Case "arcsin("
  629.                   If Degrees Then
  630.                      Temp(m) = (Atn(X / Sqr(-X * X + 1))) * RAD_TO_DEG
  631.                   Else
  632.                      Temp(m) = Atn(X / Sqr(-X * X + 1))
  633.                   End If
  634.                   
  635.                Case "arccos("
  636.                   If Degrees Then
  637.                      Temp(m) = (Atn(-X / Sqr(-X * X + 1)) + 2 * Atn(1)) * RAD_TO_DEG
  638.                   Else
  639.                      Temp(m) = Atn(-X / Sqr(-X * X + 1)) + 2 * Atn(1)
  640.                   End If
  641.                   
  642.                Case "arcsec("
  643.                   If Degrees Then
  644.                      Temp(m) = (Atn(X / Sqr(X * X - 1)) + (Sgn(X) - 1) * (2 * Atn(1))) * RAD_TO_DEG
  645.                   Else
  646.                      Temp(m) = Atn(X / Sqr(X * X - 1)) + (Sgn(X) - 1) * (2 * Atn(1))
  647.                   End If
  648.                   
  649.                Case "arccosec("
  650.                   If Degrees Then
  651.                      Temp(m) = (Atn(X / Sqr(X * X - 1)) + (Sgn(X) - 1) * (2 * Atn(1))) * RAD_TO_DEG
  652.                   Else
  653.                      Temp(m) = Atn(X / Sqr(X * X - 1)) + (Sgn(X) - 1) * (2 * Atn(1))
  654.                   End If
  655.                   
  656.                Case "arccotan("
  657.                   If Degrees Then
  658.                      Temp(m) = (Atn(X * DEG_TO_RAD) + 2 * Atn(1)) * RAD_TO_DEG
  659.                   Else
  660.                      Temp(m) = Atn(X) + 2 * Atn(1)
  661.                   End If
  662.                   
  663.                Case "sinh("
  664.                   Temp(m) = (Exp(X) - Exp(-X)) / 2
  665.                   
  666.                Case "cosh("
  667.                   Temp(m) = (Exp(X) - Exp(-X)) / (Exp(X) + Exp(-X))
  668.                   
  669.                Case "tanh("
  670.                   Temp(m) = (Exp(X) - Exp(-X)) / (Exp(X) + Exp(-X))
  671.                   
  672.                Case "sech("
  673.                   Temp(m) = 2 / (Exp(X) + Exp(-X))
  674.                   
  675.                Case "cosech("
  676.                   Temp(m) = 2 / (Exp(X) - Exp(-X))
  677.                   
  678.                Case "cotanh("
  679.                   Temp(m) = (Exp(X) + Exp(-X)) / (Exp(X) - Exp(-X))
  680.                   
  681.                Case "arcsinh("
  682.                   Temp(m) = Log(X + Sqr(X * X + 1))
  683.                   
  684.                Case "arccosh("
  685.                   Temp(m) = Log(X + Sqr(X * X - 1))
  686.                   
  687.                Case "arctanh("
  688.                   Temp(m) = Log((1 + X) / (1 - X)) / 2
  689.                   
  690.                Case "arcsech("
  691.                   Temp(m) = Log((Sqr(-X * X + 1) + 1) / X)
  692.                   
  693.                Case "arccosech("
  694.                   Temp(m) = Log((Sgn(X) * Sqr(X * X + 1) + 1) / X)
  695.                   
  696.                Case "arccotanh("
  697.                   Temp(m) = Log((X + 1) / (X - 1)) / 2
  698.                   
  699.                Case "log10("
  700.                   Temp(m) = Log(X) / Log(10)
  701.                   
  702.                Case "log2("
  703.                   Temp(m) = Log(X) / Log(2)
  704.                   
  705.                Case "ln("    'A macro to Log
  706.                   Temp(m) = Log(X)
  707.                   
  708.                ' conversion functions
  709.                Case "deg("   ' Radians to degrees
  710.                   Temp(m) = X * RAD_TO_DEG
  711.                   
  712.                Case "rad("   ' Degrees to radians
  713.                   Temp(m) = X * DEG_TO_RAD
  714.                   
  715.                Case Else
  716.                   Err.Raise EQ_FUNCTION, "clsEquation", "Undefined Function: " & v & ")"
  717.                   Exit Sub
  718.             End Select
  719.          Else
  720.             'Must be a variable
  721.             Select Case v
  722.             Case "pi":
  723.                Temp(m) = PI
  724.                
  725.             Case "e":
  726.                Temp(m) = 2.718281828
  727.                
  728.             Case "rnd":
  729.                Temp(m) = Rnd
  730.                
  731.             Case Else
  732.                eSpace = ER_VAR
  733.                Temp(m) = CDbl(Vars(Temp(m)))
  734.                eSpace = ER_NONE
  735.             End Select
  736.          End If
  737.       End Select
  738.    Next i
  739.    
  740.    dAnswer = CDbl(Temp(GetRight(0, Temp)))
  741.    Dirty = False
  742.    Exit Sub
  743.    
  744. SolveError:
  745.    Select Case Err
  746.    'Overflow, division by 0, internal errors...
  747.    Case 6, 11, EQ_PAREN To EQ_NAME
  748.       Err.Raise Err, "clsEquation", Err.Description
  749.    Case 5:
  750.       Select Case eSpace
  751.          Case ER_VAR
  752.             Err.Raise EQ_VARIABLE, "clsEquation", "Undefined Variable: " & v
  753.          Case Else
  754.             Err.Raise Err, "clsEquation", Err.Description
  755.       End Select
  756.    Case Else
  757.       Err.Raise EQ_INVALID, "clsEquation", "Invalid Equation"
  758.    End Select
  759. End Sub
  760. Public Property Get Var(Name As String) As Double
  761.    On Error GoTo GetError
  762.    
  763.    Var = CDbl(Vars(Name))
  764.    Exit Property
  765.    
  766. GetError:
  767.    Var = 0#
  768. End Property
  769.  
  770. Public Property Let Var(Name As String, Num As Double)
  771.    On Error Resume Next
  772.    Dirty = True
  773.    Vars.Remove Name
  774.    Vars.Add Num, Name
  775. End Property
  776.  
  777. Private Sub Class_Initialize()
  778.    Dirty = False
  779.    Parsed = True
  780.    Degrees = False
  781. End Sub
  782.  
  783.  
  784.