def test_and():
    f1 = AutoDiff(name='x', val=3)
    f2 = AutoDiff(name='y', val=5)
    u = AutoDiffVector((f1, f2))
    y = AutoDiffVector((f2, 8))
    np.testing.assert_array_equal(u, u) and np.testing.assert_array_equal(
        y, y), "And failed"
def test_or():
    f1 = AutoDiff(name='x', val=3)
    f2 = AutoDiff(name='y', val=5)
    u = AutoDiffVector((f1, f2))
    y = AutoDiffVector((f2, 8))
    assert u == [3, 5] or y == [0, 0], "Or failed"
    assert u == [3, 5] or y == [5, 8], "Or failed"
def test_composite():
    f1 = AutoDiff(name='x', val=np.pi/4)
    f2 = AutoDiff(name='y', val=np.pi / 2)
    u = AutoDiffVector((f1, f2))
    v = AutoDiffVector([f1, np.pi])
    z = AutoDiffVector((f2, -f1))
    np.testing.assert_array_almost_equal(ad.cos(ad.sin(u)),
                                         [0.7602445970756302, 0.5403023058681398]), "Composite failed"
    J, order = (ad.cos(ad.sin(u))).get_jacobian()
    np.testing.assert_array_almost_equal(J, [[-0.4593626849327842, 0], [0, 0]]), "Composite failed"
    np.testing.assert_array_almost_equal(ad.cos(ad.sin(v)),
                                         [0.7602445970756302, 1]), "Composite failed"
    J, order = (ad.cos(ad.sin(v))).get_jacobian()
    np.testing.assert_array_almost_equal(J, [[-0.4593626849327842], [0]]), "Composite failed"
    np.testing.assert_array_almost_equal(u*ad.cos(ad.sin(u)),
                                         [0.597094710276033, 0.8487048774164866]), "Composite failed"
    J, order = (u*ad.cos(ad.sin(u))).get_jacobian()
    np.testing.assert_array_almost_equal(J, [[0.3994619879961, 0], [0, 0.5403023058681397]]), "Composite failed"
    np.testing.assert_array_almost_equal(z*ad.cos(ad.sin(u)),
                                         [1.194189420552066, -0.4243524387082433]), "Composite failed"
    J, order = (z*ad.cos(ad.sin(u))).get_jacobian()
    np.testing.assert_array_almost_equal(J, [[-0.7215652181590587, 0.7602445970756302],
                                             [-0.5403023058681398, 0]]), "Composite failed"
    np.testing.assert_array_almost_equal((z*ad.cos(ad.sin(u)))**2,
                                         [1.4260883721584792, 0.18007499223763337]), "Composite failed"
    J, order = ((z*ad.cos(ad.sin(u)))**2).get_jacobian()
    np.testing.assert_array_almost_equal(J, [[-1.7233710995277831, 1.815752109719],
                                             [0.4585572, 0]]), "Composite failed"
def test_vec_multiply():
    f1 = AutoDiff(name='x', val=-1)
    f2 = AutoDiff(name='y', val=3)
    u = AutoDiffVector((f1, f2))
    v = AutoDiffVector((-f2, f1))
    q = [2, 0]
    t = [4, 4]
    np.testing.assert_array_equal((u * 3).val,
                                  [-3, 9]), 'Multiplication failed'
    J, order = (u * 3).get_jacobian()
    np.testing.assert_array_equal(J, [[3, 0], [0, 3]]), "Multiplication failed"
    np.testing.assert_array_equal((-4 * u).val,
                                  [4, -12]), 'Multiplication failed'
    np.testing.assert_array_equal((u * q).val,
                                  [-2, 0]), 'Multiplication failed'
    np.testing.assert_array_equal((q * u).val,
                                  [-2, 0]), 'Multiplication failed'
    J, order = (u * t).get_jacobian()
    np.testing.assert_array_equal(J, [[4, 0], [0, 4]]), "Multiplication failed"
    J, order = (u * q).get_jacobian()
    np.testing.assert_array_equal(J, [[2, 0], [0, 0]]), 'Multiplication failed'
    J, order = (q * u).get_jacobian()
    np.testing.assert_array_equal(J, [[2, 0], [0, 0]]), 'Multiplication failed'
    J, order = (u * v).get_jacobian()
    np.testing.assert_array_equal(J,
                                  [[-3, 1], [3, -1]]), 'Multiplication failed'
    J, order = (v * u).get_jacobian()
    np.testing.assert_array_equal(J,
                                  [[-3, 1], [3, -1]]), 'Multiplication failed'
def test_lt():
    f1 = AutoDiff(name='x', val=3)
    f2 = AutoDiff(name='y', val=5)
    u = AutoDiffVector((f1, f2))
    y = AutoDiffVector((f2, 8))
    assert [0, 0] < u, "Less than failed"
    assert u < [100, 100], "Less than failed"
    assert u < y, "Less than failed"
def test_le():
    f1 = AutoDiff(name='x', val=3)
    f2 = AutoDiff(name='y', val=5)
    u = AutoDiffVector((f1, f2))
    y = AutoDiffVector((f2, 8))
    assert [3, 5] <= u, "Less than failed"
    assert u <= [100, 100], "Less than failed"
    assert u <= y, "Less than failed"
def test_gt():
    f1 = AutoDiff(name='x', val=3)
    f2 = AutoDiff(name='y', val=5)
    u = AutoDiffVector((f1, f2))
    y = AutoDiffVector((f2, 8))
    assert u > [0, 0], "Greater than failed"
    assert [100, 100] > u, "Greater than failed"
    assert y > u, "Greater than failed"
def test_instantiation_zero():
    f1 = AutoDiff(name='x', val=0)
    f2 = AutoDiff(name='y', val=0)
    u = AutoDiffVector((f1, f2))
    np.testing.assert_array_equal(u.val,
                                  [0, 0]), "Positive instantiation failed"
    J, order = u.get_jacobian()
    np.testing.assert_array_equal(
        J, [[1, 0], [0, 1]]), "Positive instantiation failed"
def test_ge():
    f1 = AutoDiff(name='x', val=3)
    f2 = AutoDiff(name='y', val=5)
    u = AutoDiffVector((f1, f2))
    y = AutoDiffVector((f2, 8))
    assert u >= [0, 0], "Greater than or equal to failed"
    assert u >= [3, 5], "Greater than or equal to failed"
    assert [100, 100] >= u, "Greater than or equal to failed"
    assert y >= u, "Greater than or equal to  failed"
def test_ne():
    f1 = AutoDiff(name='x', val=3)
    f2 = AutoDiff(name='y', val=5)
    u = AutoDiffVector((f1, f2))
    y = AutoDiffVector((f2, 8))
    q = AutoDiff(name='b0', val="string")
    assert u != 11, "Not equal failed"
    assert 11 != u, "Not equal failed"
    assert u != y, "Not equal failed"
    assert y != q, "Not equal failed"
def test_sin():
    f1 = AutoDiff(name='x', val=0)
    f2 = AutoDiff(name='y', val=np.pi/2)
    u = AutoDiffVector((f1, f2))
    v = AutoDiffVector([0, np.pi/2])
    np.testing.assert_array_almost_equal(ad.sin(u), [0, 1]), 'Sine failed'
    J, order = (ad.sin(u)).get_jacobian()
    np.testing.assert_array_almost_equal(J, [[1, 0], [0, 0]]), 'Sine failed'
    np.testing.assert_array_almost_equal(ad.sin(v), [0, 1]), 'Sine failed'
    J, order = (ad.sin(v)).get_jacobian()
    np.testing.assert_array_almost_equal(J, [[0], [0]]), 'Sine failed'
def test_xor():
    f1 = AutoDiff(name='x', val=3)
    f2 = AutoDiff(name='y', val=5)
    u = AutoDiffVector((f1, f2))
    y = AutoDiffVector((f2, 8))
    np.testing.assert_array_equal(u ^ y, [6, 13]), "Xor failed"
    np.testing.assert_array_equal(y ^ u, [6, 13]), "Xor failed"
    try:
        assert (u ^ y) == 1, "Xor failed"
    except ValueError:
        print("Caught error as expected")
def test_double_instantiation():
    try:
        AutoDiffVector(name='x', val=3, trace=3)
    except TypeError:
        print("Caught error as expected")
    f1 = AutoDiff(name='x', val=1)
    f2 = AutoDiff(name='y', val=3)
    try:
        AutoDiffVector((f1, f2), f1)
    except TypeError:
        print("Caught error as expected")
def test_tan():
    f1 = AutoDiff(name='x', val=-2)
    f2 = AutoDiff(name='y', val=np.pi/8)
    u = AutoDiffVector((f1, f2))
    np.testing.assert_array_almost_equal(ad.tan(u).val, [2.18504, 0.414214]), 'Tan failed'
    J, order = (ad.tan(u)).get_jacobian()
    np.testing.assert_array_almost_equal(J, [[5.774399, 0], [0, 1.171573]], decimal=4), 'Tan failed'
    v = AutoDiffVector([np.pi/2, 0])
    try:
        np.testing.assert_array_almost_equal(ad.tan(v).val, [2.18504, 0.414214]), 'Tan failed'
    except TypeError:
        print("Caught error as expected")
def test_log():
    f1 = AutoDiff(name='x', val=1)
    f2 = AutoDiff(name='y', val=3)
    u = AutoDiffVector((f1, f2))
    v = AutoDiffVector((-f1, -f2))
    np.testing.assert_array_equal(ad.log(u),
                                  [np.log(1), np.log(3)]), "Log failed"
    J, order = (ad.log(u)).get_jacobian()
    np.testing.assert_array_almost_equal(J,
                                         [[1, 0], [0, 0.333333]]), "Log failed"
    try:
        np.testing.assert_array_almost_equal(ad.log(v),
                                             [1, 0.04978706836786395])
    except ValueError:
        print("Caught error as expected ")
def test_abs():
    f1 = AutoDiff(name='x', val=-3)
    f2 = AutoDiff(name='y', val=5)
    r = AutoDiff(name='b0', val="string")
    u = AutoDiffVector((f1, f2))
    v = AutoDiffVector((r, r))
    np.testing.assert_array_equal(abs(u), [3, 5]), "Abs val failed"
    try:
        (abs(v))
    except ValueError:
        print("Caught error as expected")
    try:
        (abs(u)).get_jacobian()
    except AttributeError:
        print("Caught error as expected")
def test_euler():
    f1 = AutoDiff(name='x', val=0)
    f2 = AutoDiff(name='y', val=3)
    u = AutoDiffVector((f1, f2))
    v = AutoDiffVector((-f1, -f2))
    np.testing.assert_array_equal(
        ad.exp(u), [1, 20.085536923187664]), "Euler's number failed"
    J, order = (ad.exp(u)).get_jacobian()
    np.testing.assert_array_almost_equal(
        J, [[1, 0], [0, 20.085537]]), "Euler's number failed"
    np.testing.assert_array_almost_equal(
        ad.exp(v), [1, 0.04978706836786395]), "Euler's number failed"
    J, order = (ad.exp(v)).get_jacobian()
    np.testing.assert_array_almost_equal(
        J, [[-1, 0], [0, -0.049787]]), "Euler's number failed"
def test_str():
    f1 = AutoDiff(name='x', val=3.3333)
    f2 = AutoDiff(name='y', val=-5.888)
    u = AutoDiffVector((f1, f2))
    assert str(
        u
    ) == "[{'val': 3.3333, 'd_x': 1},{'val': -5.888, 'd_y': 1}]", "Str failed"
def test_duplicate_instantiation():
    f1 = AutoDiff(name='x', val=1)
    f2 = AutoDiff(name='x', val=3)
    try:
        AutoDiffVector((f1, f2))
    except Exception:
        print("Caught error as expected")
def test_vec_subtract():
    f1 = AutoDiff(name='x', val=-1)
    f2 = AutoDiff(name='y', val=3)
    u = AutoDiffVector((f1, f2))
    v = AutoDiffVector((-f2, f1))
    q = [2, 1.5]
    np.testing.assert_array_equal((u - q).val, [-3, 1.5]), 'Subtraction failed'
    np.testing.assert_array_equal((q - u).val, [3, -1.5]), 'Subtraction failed'
    J, order = (u - q).get_jacobian()
    np.testing.assert_array_equal(J, [[1, 0], [0, 1]]), 'Subtraction failed'
    J, order = (q - u).get_jacobian()
    np.testing.assert_array_equal(J, [[-1, 0], [0, -1]]), 'Subtraction failed'
    np.testing.assert_array_equal((u - v).val, [2, 4]), 'Subtraction failed'
    np.testing.assert_array_equal((v - u).val, [-2, -4]), 'Subtraction failed'
    J, order = (u - v).get_jacobian()
    np.testing.assert_array_equal(J, [[1, 1], [-1, 1]]), 'Subtraction failed'
def test_csc():
    f1 = AutoDiff(name='x', val=-2)
    f2 = AutoDiff(name='y', val=np.pi / 8)
    u = AutoDiffVector((f1, f2))
    np.testing.assert_array_almost_equal(ad.csc(u).val, [-1.09975, 2.613126]), 'Cosecant failed'
    J, order = (ad.csc(u)).get_jacobian()
    np.testing.assert_array_almost_equal(J, [[0.5033, 0], [0, -6.3086]], decimal=4), 'Cosecant failed'
def test_sec():
    f1 = AutoDiff(name='x', val=0)
    f2 = AutoDiff(name='y', val=np.pi)
    u = AutoDiffVector((f1, f2))
    np.testing.assert_array_almost_equal(ad.sec(u).val, [1, -1]), 'Secant failed'
    J, order = (ad.sec(u)).get_jacobian()
    np.testing.assert_array_almost_equal(J, [[0, 0], [0, 0]], decimal=4), 'Secant failed'
def test_cot():
    f1 = AutoDiff(name='x', val=4)
    f2 = AutoDiff(name='y', val=np.pi/8)
    u = AutoDiffVector((f1, f2))
    np.testing.assert_array_almost_equal(ad.cot(u).val, [0.863691, 2.414214]), 'Cotangent failed'
    J, order = (ad.cot(u)).get_jacobian()
    np.testing.assert_array_almost_equal(J, [[-1.746, 0], [0, -6.8284]], decimal=4), 'Cotangent failed'
def test_shift():
    f1 = AutoDiff(name='x', val=3)
    f2 = AutoDiff(name='y', val=4)
    u = AutoDiffVector((f1, f2))
    np.testing.assert_array_equal(u >> 2, [16, 32]), "Shift failed"
    np.testing.assert_array_equal(u << 2, [12, 16]), "Shift failed"
    np.testing.assert_array_equal(3 >> u, [24, 32]), "Shift failed"
    np.testing.assert_array_equal(3 << u, [24, 48]), "Shift failed"
def test_contains():
    f1 = AutoDiff(name='x', val=3)
    f2 = AutoDiff(name='y', val=4)
    u = AutoDiffVector((f1, f2))
    try:
        assert 2 in u
    except NotImplementedError:
        print("Caught error as expected")
def test_bool():
    f1 = AutoDiff(name='x', val=0)
    f2 = AutoDiff(name='y', val=0)
    u = AutoDiffVector((f1, f2))
    try:
        bool(u)
    except TypeError:
        print("Caught error as expected")
def test_composition():
    f1 = AutoDiff(name='x', val=5)
    f2 = AutoDiff(name='y', val=3)
    u = AutoDiffVector((f1, f2))
    v = AutoDiffVector((-f2, -f2))
    z = (u + v) * u * (1 / v)
    np.testing.assert_array_almost_equal(z,
                                         [(-10 / 3), 0]), "Composition failed"
    J, order = (z.get_jacobian())
    np.testing.assert_array_almost_equal(
        J, [[-2.333333, 2.777778], [0, 0]]), "Composition failed"
    np.testing.assert_array_almost_equal(
        ad.exp(u)**2, [22026.465794806707, 403.428793492735])
    J, order = (ad.exp(u)**2).get_jacobian()
    np.testing.assert_array_almost_equal(
        J,
        [[44052.93158961341, 0], [0, 806.85758698547]]), "Composition failed"
def test__vec_add():
    f1 = AutoDiff(name='x', val=-1)
    f2 = AutoDiff(name='y', val=3)
    u = AutoDiffVector((f1, f2))
    v = AutoDiffVector((-f2, f1))
    q = [2, 1.5]
    np.testing.assert_array_equal((u + q).val, [1, 4.5]), 'Addition failed'
    np.testing.assert_array_equal((q + u).val, [1, 4.5]), 'Addition failed'
    J, order = (u + q).get_jacobian()
    np.testing.assert_array_equal(J, [[1, 0], [0, 1]]), 'Addition failed'
    J, order = (v + q).get_jacobian()
    np.testing.assert_array_equal(J, [[0, -1], [1, 0]]), 'Addition failed'
    J, order = (q + u).get_jacobian()
    np.testing.assert_array_equal(J, [[1, 0], [0, 1]]), 'Addition failed'
    np.testing.assert_array_equal((u + v).val, [-4, 2]), 'Addition failed'
    np.testing.assert_array_equal((v + u).val, [-4, 2]), 'Addition failed'
    J, order = (u + v).get_jacobian()
    np.testing.assert_array_equal(J, [[1, -1], [1, 1]]), 'Addition failed'
def test_sqrt():
    f1 = AutoDiff(name='x', val=16)
    f2 = AutoDiff(name='y', val=64)
    f3 = AutoDiff(name='z', val=-1)
    u = AutoDiffVector((f1, f2))
    u2 = AutoDiffVector((f1, f3))
    v = AutoDiffVector([16, 64])
    t = AutoDiffVector([0, 4])
    np.testing.assert_array_equal(ad.sqrt(u), [4, 8]), 'Square root failed'
    J, order = (ad.sqrt(u)).get_jacobian()
    np.testing.assert_array_equal(
        J, [[0.125, 0], [0, 0.0625]]), 'Square root failed'
    np.testing.assert_array_equal(ad.sqrt(v), [4, 8]), 'Square root failed'
    J, order = (ad.sqrt(v)).get_jacobian()
    np.testing.assert_array_equal(J, [[0], [0]]), 'Square root failed'
    np.testing.assert_array_equal(ad.sqrt(t), [0, 2]), 'Square root failed'
    try:
        ad.sqrt(u2)
    except ValueError:
        print("Caught error as expected")
def test_exponentiation():
    f1 = AutoDiff(name='x', val=3)
    f2 = AutoDiff(name='y', val=5)
    u = AutoDiffVector((f1, f2))
    np.testing.assert_array_almost_equal(u**2,
                                         [9, 25]), "Exponentiation failed"
    J, order = (u**2).get_jacobian()
    np.testing.assert_array_almost_equal(
        J, [[6, 0], [0, 10]]), "Exponentiation failed"
    J, order = (2**u).get_jacobian()
    np.testing.assert_array_almost_equal(
        J, [[5.545177, 0], [0, 22.18071]]), "Exponentiation failed"