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

1import pytest 

2import numpy as np 

3 

4from Adifpy.differentiate.dual_number import DualNumber 

5 

6 

7class TestDualNumber(DualNumber): 

8 """Test class for DualNumber""" 

9 

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)) 

15 

16 def test_add(self): 

17 with pytest.raises(TypeError): 

18 z1 = DualNumber(1, 2) 

19 

20 # Adding a string to a dual number is invalid 

21 z1 + '1' 

22 '1' + z1 

23 

24 d = DualNumber(1, 2) 

25 

26 # Ensure integer addition works 

27 d1 = d + 1 

28 assert d1.real == 2 and d1.dual == 2 

29 

30 # Ensure floating addition works 

31 d2 = d + 2.5 

32 assert d2.real == 3.5 and d2.dual == 2 

33 

34 # Ensure dual number addition works 

35 d3 = d + DualNumber(2, 4) 

36 assert d3.real == 3 and d3.dual == 6 

37 

38 def test_mul(self): 

39 with pytest.raises(TypeError): 

40 z1 = DualNumber(1, 2) 

41 z1 * '1' 

42 '1' * z1 

43 

44 d = DualNumber(1, 2) 

45 # Ensure integer multiplication works 

46 d1 = d * 2 

47 assert d1.real == 2 and d1.dual == 4 

48 

49 # Ensure floating multiplication works 

50 d2 = d * 2.5 

51 assert d2.real == 2.5 and d2.dual == 5.0 

52 

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 

58 

59 def test_sub(self): 

60 with pytest.raises(TypeError): 

61 z1 = DualNumber(1, 2) 

62 z1 - '1' 

63 '1' - z1 

64 

65 d = DualNumber(1, 2) 

66 # Ensure integer subtraction works 

67 d1 = d - 1 

68 assert d1.real == 0 and d1.dual == 2 

69 

70 # Ensure floating subtraction works 

71 d2 = d - 2.5 

72 assert d2.real == -1.5 and d2.dual == 2 

73 

74 # Ensure dual number subtraction works 

75 d3 = d - DualNumber(2, 4) 

76 assert d3.real == -1 and d3.dual == -2 

77 

78 def test_truediv(self): 

79 with pytest.raises(TypeError): 

80 z1 = DualNumber(1, 2) 

81 z1 / '1' 

82 '1' / z1 

83 

84 d = DualNumber(2, 4) 

85 # Ensure integer division works 

86 d1 = d / 2 

87 assert d1.real == 1 and d1.dual == 2 

88 

89 # Ensure floating division works 

90 d2 = d / 2.5 

91 assert d2.real == 0.8 and d2.dual == 1.6 

92 

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) 

98 

99 def test_pow(self): 

100 with pytest.raises(TypeError): 

101 z1 = DualNumber(1, 2) 

102 z1 ** '1' 

103 '1' ** z1 

104 

105 d = DualNumber(3, 4) 

106 dd = DualNumber(5, 6) 

107 

108 d1 = d ** 2 

109 d2 = d ** -1.5 

110 

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) 

117 

118 def test_neg(self): 

119 d = DualNumber(1, 2) 

120 negd = -d 

121 assert negd.real == -1 and negd.dual == -2 

122 

123 def test_radd(self): 

124 d = DualNumber(1, 2) 

125 

126 d1 = 1 + d 

127 d2 = 2.5 + d 

128 

129 assert d1.real == 2 and d1.dual == 2 and d2.real == 3.5 and d2.dual == 2 

130 

131 def test_rmul(self): 

132 d = DualNumber(1, 2) 

133 

134 d1 = 2 * d 

135 d2 = 2.5 * d 

136 

137 assert d1.real == 2 and d1.dual == 4 and d2.real == 2.5 and d2.dual == 5.0 

138 

139 def test_rsub(self): 

140 d = DualNumber(1, 2) 

141 

142 d1 = 1 - d 

143 d2 = 0.5 - d 

144 

145 assert d1.real == 0 and d1.dual == 2 and d2.real == -0.5 and d2.dual == 2 

146 

147 def test_rtruediv(self): 

148 d = DualNumber(2, 3) 

149 

150 d1 = 6 / d 

151 d2 = 4.8 / d 

152 

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) 

156 

157 def test_rpow(self): 

158 d = DualNumber(2, 3) 

159 

160 d1 = 5 ** d 

161 d2 = 1.5 ** d 

162 

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)