diff --git a/symboCalc.py b/symboCalc.py
index fb8f50cb6b1be339f5cda2fdf9fdbbe4428e4f60..e1980018403235629f43f4b9e3e2ceed7a67786e 100644
--- a/symboCalc.py
+++ b/symboCalc.py
@@ -1,10 +1,10 @@
 # Jack Eckert
 
 # dependencies
-from abc import ABC, abstractmethod
 import math
+from typing import Any
 
-# abstract base class for functions
+# base class for functions
 
 # arg is the argument of the function, which by default is the identity function represented
 # by the string 'x'. Any string will work and acts as a marker to allow the program to identify
@@ -12,7 +12,7 @@ import math
 
 # coef is the coefficient of the function, should always be an integer or float and by default
 # is one. 
-class BaseFunction(ABC):
+class BaseFunction():
     def __init__(self, coef=None, arg=None):
         if coef == None:
             self.__coefficient = 1
@@ -40,9 +40,19 @@ class BaseFunction(ABC):
     def integrateCoef(self, k):
         self.__coefficient *= k
 
+    def __neg__(self):
+        return type(self)(-self.getCoef(), self.getArg())
+
+    def __eq__(self, other):
+        if not(isinstance(other, type(self))):
+            return False
+        return (self.getArg() == other.getArg() and self.getCoef() == other.getCoef())
+
     def __str__(self):
         if self.getCoef() == 1:
             coefficientString = ''
+        elif self.getCoef() == -1:
+            coefficientString = '-'
         else:
             coefficientString = round(self.getCoef(), 3)
         return coefficientString
@@ -50,9 +60,11 @@ class BaseFunction(ABC):
     def __repr__(self):
         return str(self)
 
-    @abstractmethod
-    def derive(self):
-        pass
+    def derive(self, shell):
+        if isinstance(self.getArg(), str):
+            return shell
+        else:
+            return [shell.getArg().derive(), shell]
 
 # power function, i.e. a function raised to a constant power.
 class Power(BaseFunction):
@@ -66,6 +78,15 @@ class Power(BaseFunction):
     def setExp(self):
         return self.__exponent
     
+    def __neg__(self):
+        return type(self)(-self.getCoef(), self.getArg(), self.getExp())
+    
+    def __eq__(self, other):
+        return (super().__eq__(other) and self.getExp() == other.getExp())
+    
+    def __ne__(self, other):
+        return not(self.__eq__(other))
+    
     def __str__(self):
         coefficientString = super().__str__()
 
@@ -88,13 +109,8 @@ class Power(BaseFunction):
         else:
             shell = Power(self.getCoef() * self.getExp(), self.getArg(), self.getExp() - 1)
 
-        # base derivative, or chain rule if the argument is a different function
-        if isinstance(self.getArg(), str):
-            return shell
-        else:
-            return (self.getArg().derive(), shell)
-        
-
+        # derivation
+        return super().derive(shell)
         
 # exponential function, i.e. a constant raised to a function power.
 class Exponential(BaseFunction):
@@ -113,26 +129,126 @@ class Exponential(BaseFunction):
     def setBase(self, new):
         self.__base = new
 
+    def __neg__(self):
+        return type(self)(-self.getCoef(), self.getArg(), self.getBase())
+
     def __str__(self):
         coefficientString = super().__str__()
         return f"{coefficientString}exp({self.getArg()})"
     
+    def __eq__(self, other):
+        return (super().__eq__(other) and self.getBase() == other.getBase())
+    
     def derive(self):
-        if isinstance(self.getArg(), str):
-            return self
-        else:
-            return (self.getArg().derive(), self)
-        
-class Sin():
+        shell = self
+        return super().derive(shell)
+
+# sine function  
+class Sine(BaseFunction):
+    def __init__(self, coef=None, arg=None):
+        super().__init__(coef, arg)
+
+    def __str__(self):
+        coefficientString = super().__str__()
+        return f"{coefficientString}sin({self.getArg()})"
     
+    def derive(self):
+        shell = Cosine(self.getCoef(), self.getArg())
+        return super().derive(shell)
 
+# cosine function 
+class Cosine(BaseFunction):
+    def __init__(self, coef=None, arg=None):
+        super().__init__(coef, arg)
+
+    def __str__(self):
+        coefficientString = super().__str__()
+        return f"{coefficientString}cos({self.getArg()})"
+    
+    def derive(self):
+        shell = -Sine(self.getCoef(), self.getArg())
+        return super().derive(shell)
 
-# TODO
 class Equation():
     def __init__(self, eqList):
+        self.__eqList = eqList
+        for i, term in enumerate(self.__eqList):
+            if not(isinstance(term, list)):
+                self.__eqList[i] = [term]
+
+    def __iter__(self):
+        self.index = -1
+        return self
+    
+    def __next__(self):
+        if self.index < len(self.__eqList) - 1:
+            self.index += 1
+            return self.__eqList[self.index]
+        else:
+            raise StopIteration
+
+    def getEqList(self):
+        return self.__eqList
+    
+    def setEqList(self, new):
+        self.__eqList = new
+
+    def __getitem__(self, i):
+        return self.__eqList[i]
+    
+    def __setitem__(self, i, new):
+        self.__eqList[i] = new
+
+    def addTerm(self, new):
+        if not(isinstance(new, list)):
+            new = [new]
+        self.__eqList.append(new)
+
+    def removeAt(self, i):
+        del self.__eqList[i]
+
+    def __str__(self):
+        strList = []
+        for term in self:
+            termString = ''
+            for seg in term:
+                termString += f"({seg})"
+            strList.append(termString)
+        return " + ".join(strList)
+    
+    def __mul__(self, k):
+        copy = Equation(self.__eqList)
+        for term in copy:
+            term.insert(0, k)
+        return copy
+    
+    def __rmul__(self, k):
+        copy = Equation(self.__eqList)
+        for term in copy:
+            term.insert(0, k)
+        return copy
+    
+    def __add__(self, k):
+        copy = Equation(self.__eqList)
+        copy.addTerm(k)
+        return copy
+
+    def __radd__(self, k):
+        copy = Equation(self.__eqList)
+        copy.addTerm(k)
+        return copy
+    
+    def __sub__(self, k):
+        return self + -k
+    
+    def __rsub__(self, k):
+        return -self + k
+    
+    #TODO
+    def simplify(self):
         pass
 
 # Testing
 if __name__ == "__main__":
-    eq1 = Exponential(arg=Power(exp=2))
-    print(eq1.derive())
\ No newline at end of file
+    eq1 = Equation([[Power(exp=2), Cosine()], Sine()])
+    print(eq1 - Cosine())
\ No newline at end of file