Coverage for Adifpy/test/test_dual_number.py: 16%
98 statements
« prev ^ index » next coverage.py v6.5.0, created at 2022-11-22 19:44 -0500
« prev ^ index » next coverage.py v6.5.0, created at 2022-11-22 19:44 -0500
1import pytest
2import numpy as np
4from Adifpy.differentiate.dual_number import DualNumber
7class TestDualNumber(DualNumber):
8 """Test class for DualNumber"""
10 def test_init(self):
11 d = DualNumber(1, 2)
12 assert isinstance(d, DualNumber) and \
13 isinstance(d.real, (int, float)) and \
14 isinstance(d.dual, (int, float))
16 def test_add(self):
17 with pytest.raises(TypeError):
18 z1 = DualNumber(1, 2)
20 # Adding a string to a dual number is invalid
21 z1 + '1'
22 '1' + z1
24 d = DualNumber(1, 2)
26 # Ensure integer addition works
27 d1 = d + 1
28 assert d1.real == 2 and d1.dual == 2
30 # Ensure floating addition works
31 d2 = d + 2.5
32 assert d2.real == 3.5 and d2.dual == 2
34 # Ensure dual number addition works
35 d3 = d + DualNumber(2, 4)
36 assert d3.real == 3 and d3.dual == 6
38 def test_mul(self):
39 with pytest.raises(TypeError):
40 z1 = DualNumber(1, 2)
41 z1 * '1'
42 '1' * z1
44 d = DualNumber(1, 2)
45 # Ensure integer multiplication works
46 d1 = d * 2
47 assert d1.real == 2 and d1.dual == 4
49 # Ensure floating multiplication works
50 d2 = d * 2.5
51 assert d2.real == 2.5 and d2.dual == 5.0
53 # Ensure dual number multiplication works
54 d3 = DualNumber(2, 4)
55 d4 = d * d3
56 assert d4.real == d.real * d3.real - d.dual * d3.dual and \
57 d4.dual == d.real * d3.dual + d3.real * d.dual
59 def test_sub(self):
60 with pytest.raises(TypeError):
61 z1 = DualNumber(1, 2)
62 z1 - '1'
63 '1' - z1
65 d = DualNumber(1, 2)
66 # Ensure integer subtraction works
67 d1 = d - 1
68 assert d1.real == 0 and d1.dual == 2
70 # Ensure floating subtraction works
71 d2 = d - 2.5
72 assert d2.real == -1.5 and d2.dual == 2
74 # Ensure dual number subtraction works
75 d3 = d - DualNumber(2, 4)
76 assert d3.real == -1 and d3.dual == -2
78 def test_truediv(self):
79 with pytest.raises(TypeError):
80 z1 = DualNumber(1, 2)
81 z1 / '1'
82 '1' / z1
84 d = DualNumber(2, 4)
85 # Ensure integer division works
86 d1 = d / 2
87 assert d1.real == 1 and d1.dual == 2
89 # Ensure floating division works
90 d2 = d / 2.5
91 assert d2.real == 0.8 and d2.dual == 1.6
93 # Ensure dual number division works
94 d3 = DualNumber(4, 8)
95 d4 = d / d3
96 assert d4.real == d.real / d3.real and \
97 d4.dual == (d.dual * d3.real - d3.dual * d.real) / (d3.real ** 2)
99 def test_pow(self):
100 with pytest.raises(TypeError):
101 z1 = DualNumber(1, 2)
102 z1 ** '1'
103 '1' ** z1
105 d = DualNumber(3, 4)
106 dd = DualNumber(5, 6)
108 d1 = d ** 2
109 d2 = d ** -1.5
111 assert d1.real == pow(d.real, dd.real) and \
112 d1.dual == dd.dual * np.log(d.real) * pow(d.real, dd.real) + \
113 d.dual * dd.real * pow(d.real, dd.real - 1)
114 assert d2.real == pow(d.real, dd.real) and \
115 d2.dual == dd.dual * np.log(d.real) * pow(d.real, dd.real) + \
116 d.dual * dd.real * pow(d.real, dd.real - 1)
118 def test_neg(self):
119 d = DualNumber(1, 2)
120 negd = -d
121 assert negd.real == -1 and negd.dual == -2
123 def test_radd(self):
124 d = DualNumber(1, 2)
126 d1 = 1 + d
127 d2 = 2.5 + d
129 assert d1.real == 2 and d1.dual == 2 and d2.real == 3.5 and d2.dual == 2
131 def test_rmul(self):
132 d = DualNumber(1, 2)
134 d1 = 2 * d
135 d2 = 2.5 * d
137 assert d1.real == 2 and d1.dual == 4 and d2.real == 2.5 and d2.dual == 5.0
139 def test_rsub(self):
140 d = DualNumber(1, 2)
142 d1 = 1 - d
143 d2 = 0.5 - d
145 assert d1.real == 0 and d1.dual == 2 and d2.real == -0.5 and d2.dual == 2
147 def test_rtruediv(self):
148 d = DualNumber(2, 3)
150 d1 = 6 / d
151 d2 = 4.8 / d
153 assert d1.real == 3 and d1.dual == -d.dual * 6 / \
154 pow(d.real, 2) and d2.real == 2.4 and d2.dual == - \
155 d.dual * 4.8 / pow(d.real, 2)
157 def test_rpow(self):
158 d = DualNumber(2, 3)
160 d1 = 5 ** d
161 d2 = 1.5 ** d
163 assert d1.real == pow(5, 2) and d1.dual == 3 * np.log(5) * pow(5, 2)
164 assert d2.real == pow(1.5, 2) and d2.dual == 3 * \
165 np.log(1.5) * pow(1.5, 2)