import simbios.simtk as simtk
import simbios.std as std
import unittest

class ZeroFunction(simtk.Function.Constant):
    def __init__(self):
        super(ZeroFunction, self).__init__(0, 0)

class IdentityFunction(simtk.Function):
    def __init__(self):
        super(IdentityFunction, self).__init__()
    def calcValue(self, x):
        return x[0]
    def calcDerivative(self, derivComponents, x):
        if 1 == len(deriveComponents):
            return 1.0
        else:
            return 0.0
    def getArgumentSize(self):
        return 1
    def getMaxDerivativeOrder(self):
        return 1000

class DifferenceFunction(simtk.Function.Linear):
    def __init__(self):
        super(DifferenceFunction, self).__init__((1.0, -1.0, 0.0))

class TestFunction(unittest.TestCase):
    def testZeroFunction(self):
        z = ZeroFunction()
        self.assertEqual(z.getArgumentSize(), 0)
        self.assertTrue(z.getMaxDerivativeOrder() > 4)
        v = simtk.Vector_[float](0)
        self.assertEqual(z.calcValue(v), 0)
        d = simtk.Array[int](1, 0)
        self.assertEqual(z.calcDerivative(d, v), 0)
        
    def testUnityFunction(self):
        uf = simtk.Function.Constant(1.0, 0)
        self.assertEqual(uf.getArgumentSize(), 0)
        self.assertTrue(uf.getMaxDerivativeOrder() > 4)
        v = simtk.Vector_[float](0)
        self.assertEqual(uf.calcValue(v), 1.0)
        d = simtk.Array[int](1, 0)
        self.assertEqual(uf.calcDerivative(d, v), 0)
        # Need automatic conversion of tuple, list to simtk.Vector_[float]
        self.assertEqual(uf.calcValue([]), 1.0)
        
    def testIdentityFunction(self):
        idfn = IdentityFunction()
        self.assertEqual(idfn.getArgumentSize(), 1)
        self.assertTrue(idfn.getMaxDerivativeOrder() > 4)
        self.assertEqual(idfn.calcValue([1.3]), 1.3)
        
    def testDifferenceFunction(self):
        dffn = DifferenceFunction()
        self.assertEqual(dffn.calcValue([7.5, 6.0]), 1.5)

if __name__ == '__main__':
    unittest.main()

