@@ -4,224 +4,229 @@ import Testing
44
55@Suite
66struct TestRegisteredDerivatives {
7- // These tests are more about the derivatives being correctly registered than the correct values. Should probably use a form of
8- // `.isApproximatelyEqual(to:)` for the results in the future but that doesn't combine too well with a SIMD vector comparison.
7+ // These tests are more about the derivatives being correctly registered than the correct values. We're only checking the first value for simds since we run the computation on the same values and only checking the first result makes using `.isApproximatelyEqual(to:)` a lot easier.
98 @Test
109 func
1110 testExp( )
1211 {
1312 let vwpb = valueWithPullback ( at: 2.0 , of: Float . exp)
14- #expect( vwpb. value == 7.38905609893065 )
15- #expect( vwpb. pullback ( 1 ) == 7.38905609893065 )
13+ #expect( vwpb. value. isApproximatelyEqual ( to : 7.38905609893065 ) )
14+ #expect( vwpb. pullback ( 1 ) . isApproximatelyEqual ( to : 7.38905609893065 ) )
1615 }
1716
1817 @Test
1918 func testExpMinusOne( ) {
2019 let vwpb = valueWithPullback ( at: 2.0 , of: Double . expMinusOne ( _: ) )
21- #expect( vwpb. value == 6.38905609893065 )
22- #expect( vwpb. pullback ( 1 ) == 7.38905609893065 )
20+ #expect( vwpb. value. isApproximatelyEqual ( to : 6.38905609893065 ) )
21+ #expect( vwpb. pullback ( 1 ) . isApproximatelyEqual ( to : 7.38905609893065 ) )
2322 }
2423
2524 @Test
2625 func testCosh( ) {
2726 let vwpb = valueWithPullback ( at: SIMD2 < Float > ( repeating: 2.0 ) , of: SIMD2< Float> . cosh)
28- #expect( vwpb. value == . init ( repeating : 3.7621956 ) )
29- #expect( vwpb. pullback ( . one) == . init ( repeating : 3.6268604 ) )
27+ #expect( vwpb. value [ 0 ] . isApproximatelyEqual ( to : 3.7621956 ) )
28+ #expect( vwpb. pullback ( . one) [ 0 ] . isApproximatelyEqual ( to : 3.6268604 ) )
3029 }
3130
3231 @Test
3332 func testSinh( ) {
3433 let vwpb = valueWithPullback ( at: SIMD4 < Float > ( repeating: 2.0 ) , of: SIMD4< Float> . sinh)
35- #expect( vwpb. value == . init ( repeating : 3.6268604 ) )
36- #expect( vwpb. pullback ( . one) == . init ( repeating : 3.7621956 ) )
34+ #expect( vwpb. value [ 0 ] . isApproximatelyEqual ( to : 3.6268604 ) )
35+ #expect( vwpb. pullback ( . one) [ 0 ] . isApproximatelyEqual ( to : 3.7621956 ) )
3736 }
3837
3938 @Test
4039 func testTanh( ) {
4140 let vwpb = valueWithPullback ( at: SIMD8 < Float > ( repeating: 2.0 ) , of: SIMD8< Float> . tanh)
42- #expect( vwpb. value == . init ( repeating : 0.9640276 ) )
43- #expect( vwpb. pullback ( . one) == . init ( repeating : 0.07065083 ) )
41+ #expect( vwpb. value [ 0 ] . isApproximatelyEqual ( to : 0.9640276 ) )
42+ #expect( vwpb. pullback ( . one) [ 0 ] . isApproximatelyEqual ( to : 0.07065083 ) )
4443 }
4544
4645 @Test
4746 func testCos( ) {
4847 let vwpb = valueWithPullback ( at: SIMD16 < Float > ( repeating: . pi / 2 ) , of: SIMD16< Float> . cos)
49- #expect( vwpb. value == . init ( repeating : 7.54979E-08 ) )
50- #expect( vwpb. pullback ( . one) == . init ( repeating : - 1 ) )
48+ #expect( vwpb. value [ 0 ] . isApproximatelyEqual ( to : 0 , absoluteTolerance : . ulpOfOne ) )
49+ #expect( vwpb. pullback ( . one) [ 0 ] . isApproximatelyEqual ( to : - 1 ) )
5150 }
5251
5352 @Test
5453 func testSin( ) {
5554 let vwpb = valueWithPullback ( at: SIMD32 < Float > ( repeating: . pi / 2 ) , of: SIMD32< Float> . sin)
56- #expect( vwpb. value == . init ( repeating : 1 ) )
57- #expect( vwpb. pullback ( . one) == . init ( repeating : 7.54979E-08 ) )
55+ #expect( vwpb. value [ 0 ] . isApproximatelyEqual ( to : 1 ) )
56+ #expect( vwpb. pullback ( . one) [ 0 ] . isApproximatelyEqual ( to : 0 , absoluteTolerance : . ulpOfOne ) )
5857 }
5958
6059 @Test
6160 func testTan( ) {
6261 let vwpb = valueWithPullback ( at: SIMD64 < Float > ( repeating: . pi / 4 ) , of: SIMD64< Float> . tan)
63- #expect( vwpb. value == . init ( repeating : 0.99999994 ) )
64- #expect( vwpb. pullback ( . one) == . init ( repeating : 1.9999998 ) )
62+ #expect( vwpb. value [ 0 ] . isApproximatelyEqual ( to : 1 ) )
63+ #expect( vwpb. pullback ( . one) [ 0 ] . isApproximatelyEqual ( to : 2 ) )
6564 }
6665
6766 @Test
6867 func testLog( ) {
6968 let vwpb = valueWithPullback ( at: SIMD2 < Double > ( repeating: 2 ) , of: SIMD2< Double> . log( _: ) )
70- #expect( vwpb. value == SIMD2 < Double > ( repeating : 0.6931471805599453 ) )
71- #expect( vwpb. pullback ( SIMD2 < Double > . one) == . init ( repeating : 0.5 ) )
69+ #expect( vwpb. value [ 0 ] . isApproximatelyEqual ( to : 0.6931471805599453 ) )
70+ #expect( vwpb. pullback ( . one) [ 0 ] . isApproximatelyEqual ( to : 0.5 ) )
7271 }
7372
7473 @Test
7574 func testLogOnePlus( ) {
7675 let vwpb = valueWithPullback ( at: SIMD4 < Double > ( repeating: 3 ) , of: SIMD4< Double> . log( onePlus: ) )
77- #expect( vwpb. value == . init ( repeating : 1.3862943611198906 ) )
78- #expect( vwpb. pullback ( . one) == . init ( repeating : 0.25 ) )
76+ #expect( vwpb. value [ 0 ] . isApproximatelyEqual ( to : 1.3862943611198906 ) )
77+ #expect( vwpb. pullback ( . one) [ 0 ] . isApproximatelyEqual ( to : 0.25 ) )
7978 }
8079
8180 @Test
8281 func testAcosh( ) {
8382 let vwpb = valueWithPullback ( at: SIMD8 < Double > ( repeating: 2 ) , of: SIMD8< Double> . acosh)
84- #expect( vwpb. value == . init ( repeating : 1.3169578969248166 ) )
85- #expect( vwpb. pullback ( . one) == . init ( repeating : 1 / . sqrt( 3 ) ) )
83+ #expect( vwpb. value [ 0 ] . isApproximatelyEqual ( to : 1.3169578969248166 ) )
84+ #expect( vwpb. pullback ( . one) [ 0 ] . isApproximatelyEqual ( to : 1 / . sqrt( 3 ) ) )
8685 }
8786
8887 @Test
8988 func testAsinh( ) {
9089 let vwpb = valueWithPullback ( at: SIMD16 < Double > ( repeating: 2 ) , of: SIMD16< Double> . asinh)
91- #expect( vwpb. value == . init ( repeating : 1.4436354751788103 ) )
92- #expect( vwpb. pullback ( . one) == . init ( repeating : 1 / . sqrt( 5 ) ) )
90+ #expect( vwpb. value [ 0 ] . isApproximatelyEqual ( to : 1.4436354751788103 ) )
91+ #expect( vwpb. pullback ( . one) [ 0 ] . isApproximatelyEqual ( to : 1 / . sqrt( 5 ) ) )
9392 }
9493
9594 @Test
9695 func testAtanh( ) {
9796 let vwpb = valueWithPullback ( at: SIMD32 < Double > ( repeating: 0.5 ) , of: SIMD32< Double> . atanh)
98- #expect( vwpb. value == . init ( repeating : 0.5493061443340549 ) )
99- #expect( vwpb. pullback ( . one) == . init ( repeating : 4 / 3 ) )
97+ #expect( vwpb. value [ 0 ] . isApproximatelyEqual ( to : 0.5493061443340549 ) )
98+ #expect( vwpb. pullback ( . one) [ 0 ] . isApproximatelyEqual ( to : 4 / 3 ) )
10099 }
101100
102101 @Test
103- func testaCos ( ) {
104- let vwpb = valueWithPullback ( at: SIMD64 < Double > ( repeating: 0.5 ) , of: SIMD64< Double> . acos)
105- #expect( vwpb. value == . init ( repeating : 1.0471975511965976 ) )
106- #expect( vwpb. pullback ( . one) == . init ( repeating : - 1.1547005383792517 ) )
102+ func testAcos ( ) {
103+ let vwpb = valueWithPullback ( at: SIMD64 < Double > ( repeating: 1 / . sqrt ( 2 ) ) , of: SIMD64< Double> . acos)
104+ #expect( vwpb. value [ 0 ] . isApproximatelyEqual ( to : . pi / 4 ) )
105+ #expect( vwpb. pullback ( . one) [ 0 ] . isApproximatelyEqual ( to : - . sqrt ( 2 ) ) )
107106 }
108107
109108 @Test
110- func testaSin ( ) {
111- let vwpb = valueWithPullback ( at: 0.5 , of: Float . asin)
112- #expect( vwpb. value == 0.5235988 )
113- #expect( vwpb. pullback ( 1 ) == 1.1547005383792517 )
109+ func testAsin ( ) {
110+ let vwpb = valueWithPullback ( at: 1 / . sqrt ( 2 ) , of: Float . asin)
111+ #expect( vwpb. value. isApproximatelyEqual ( to : . pi / 4 ) )
112+ #expect( vwpb. pullback ( 1 ) . isApproximatelyEqual ( to : . sqrt ( 2 ) ) )
114113 }
115114
116115 @Test
117- func testaTan ( ) {
116+ func testAtan ( ) {
118117 let vwpb = valueWithPullback ( at: 0.5 , of: Double . atan)
119- #expect( vwpb. value == 0.46364760900080615 )
120- #expect( vwpb. pullback ( 1 ) == 0.8 )
118+ #expect( vwpb. value. isApproximatelyEqual ( to : 0.46364760900080615 ) )
119+ #expect( vwpb. pullback ( 1 ) . isApproximatelyEqual ( to : 0.8 ) )
121120 }
122121
123122 @Test
124123 func testPow( ) {
125124 let vwpb = valueWithPullback ( at: SIMD2 < Float > ( repeating: 0.5 ) , SIMD2 < Float > ( repeating: 2 ) , of: SIMD2< Float> . pow( _: _: ) )
126- #expect( vwpb. value == . init( repeating: 0.25 ) )
127- #expect( vwpb. pullback ( . one) == ( . init( repeating: 1.0 ) , . init( repeating: - 0.1732868 ) ) )
125+ #expect( vwpb. value [ 0 ] . isApproximatelyEqual ( to: 0.25 ) )
126+ let gradient = vwpb. pullback ( . one)
127+ #expect( gradient. 0 [ 0 ] . isApproximatelyEqual ( to: 1.0 ) )
128+ #expect( gradient. 1 [ 0 ] . isApproximatelyEqual ( to: - 0.1732868 ) )
128129 }
129130
130131 @Test
131132 func testPowInt( ) {
132133 let vwpb = valueWithPullback ( at: SIMD4 < Float > ( repeating: 0.5 ) , of: { x in SIMD4< Float> . pow( x, 2 ) } )
133- #expect( vwpb. value == . init ( repeating : 0.25 ) )
134- #expect( vwpb. pullback ( . one) == . init ( repeating : 1.0 ) )
134+ #expect( vwpb. value [ 0 ] . isApproximatelyEqual ( to : 0.25 ) )
135+ #expect( vwpb. pullback ( . one) [ 0 ] . isApproximatelyEqual ( to : 1 ) )
135136 }
136137
137138 @Test
138139 func testSqrt( ) {
139140 let vwpb = valueWithPullback ( at: SIMD8 < Float > ( repeating: 4 ) , of: SIMD8< Float> . sqrt)
140- #expect( vwpb. value == . init ( repeating : 2 ) )
141- #expect( vwpb. pullback ( . one) == . init ( repeating : 0.25 ) )
141+ #expect( vwpb. value [ 0 ] . isApproximatelyEqual ( to : 2 ) )
142+ #expect( vwpb. pullback ( . one) [ 0 ] . isApproximatelyEqual ( to : 0.25 ) )
142143 }
143144
144145 @Test
145146 func testRoot( ) {
146147 let vwpb = valueWithPullback ( at: SIMD16 < Float > ( repeating: 16 ) , of: { x in SIMD16< Float> . root( x, 4 ) } )
147- #expect( vwpb. value == . init ( repeating : 2 ) )
148- #expect( vwpb. pullback ( . one) == . init ( repeating : 1 / 32 ) )
148+ #expect( vwpb. value [ 0 ] . isApproximatelyEqual ( to : 2 ) )
149+ #expect( vwpb. pullback ( . one) [ 0 ] . isApproximatelyEqual ( to : 1 / 32 ) )
149150 }
150151
151152 @Test
152153 func testAtan2( ) {
153154 let vwpb = valueWithPullback ( at: SIMD32 < Float > ( repeating: 1 ) , SIMD32 < Float > ( repeating: 0 ) , of: SIMD32< Float> . atan2)
154- #expect( vwpb. value == . init( repeating: 1.5707964 ) ) // .pi / 2
155- #expect( vwpb. pullback ( . one) == ( . init( repeating: 0 ) , . init( repeating: - 1 ) ) )
155+ #expect( vwpb. value [ 0 ] . isApproximatelyEqual ( to: . pi / 2 ) )
156+ let gradient = vwpb. pullback ( . one)
157+ #expect( gradient. 0 [ 0 ] . isApproximatelyEqual ( to: 0 , absoluteTolerance: . ulpOfOne) )
158+ #expect( gradient. 1 [ 0 ] . isApproximatelyEqual ( to: - 1 ) )
156159 }
157160
158161 @Test
159162 func testErf( ) {
160163 let vwpb = valueWithPullback ( at: SIMD64 < Float > ( repeating: 0.5 ) , of: SIMD64< Float> . erf)
161- #expect( vwpb. value == . init ( repeating : 0.5204999 ) )
162- #expect( vwpb. pullback ( . one) == . init ( repeating : 0.87878263 ) )
164+ #expect( vwpb. value [ 0 ] . isApproximatelyEqual ( to : 0.5204998778 ) )
165+ #expect( vwpb. pullback ( . one) [ 0 ] . isApproximatelyEqual ( to : 0.8787825789354449 ) )
163166 }
164167
165168 @Test
166169 func testErfc( ) {
167170 let vwpb = valueWithPullback ( at: SIMD2 < Double > ( repeating: 0.5 ) , of: SIMD2< Double> . erfc)
168- #expect( vwpb. value == . init ( repeating : 0.4795001221869535 ) )
169- #expect( vwpb. pullback ( . one) == . init ( repeating : - 0.8787825789354449 ) )
171+ #expect( vwpb. value [ 0 ] . isApproximatelyEqual ( to : 1 - 0.5204998778 ) )
172+ #expect( vwpb. pullback ( . one) [ 0 ] . isApproximatelyEqual ( to : - 0.8787825789354449 ) )
170173 }
171174
172175 @Test
173176 func testExp2( ) {
174177 let vwpb = valueWithPullback ( at: SIMD4 < Double > ( repeating: 2 ) , of: SIMD4< Double> . exp2)
175- #expect( vwpb. value == . init ( repeating : 4 ) )
176- #expect( vwpb. pullback ( . one) == . init ( repeating : 4 * . log( 2 ) ) )
178+ #expect( vwpb. value [ 0 ] . isApproximatelyEqual ( to : 4 ) )
179+ #expect( vwpb. pullback ( . one) [ 0 ] . isApproximatelyEqual ( to : 4 * . log( 2 ) ) )
177180 }
178181
179182 @Test
180183 func testExp10( ) {
181184 let vwpb = valueWithPullback ( at: SIMD8 < Double > ( repeating: 2 ) , of: SIMD8< Double> . exp10)
182- #expect( vwpb. value == . init ( repeating : 100 ) )
183- #expect( vwpb. pullback ( . one) == . init ( repeating : 100 * . log( 10 ) ) )
185+ #expect( vwpb. value [ 0 ] . isApproximatelyEqual ( to : 100 ) )
186+ #expect( vwpb. pullback ( . one) [ 0 ] . isApproximatelyEqual ( to : 100 * . log( 10 ) ) )
184187 }
185188
186189 @Test
187190 func testHypot( ) {
188191 let vwpb = valueWithPullback ( at: SIMD16 < Double > ( repeating: 3 ) , SIMD16 < Double > ( repeating: 4 ) , of: SIMD16< Double> . hypot)
189- #expect( vwpb. value == . init( repeating: 5 ) )
190- #expect( vwpb. pullback ( . one) == ( . init( repeating: 3 / 5 ) , . init( repeating: 4 / 5 ) ) )
192+ #expect( vwpb. value [ 0 ] . isApproximatelyEqual ( to: 5 ) )
193+ let gradient = vwpb. pullback ( . one)
194+ #expect( gradient. 0 [ 0 ] . isApproximatelyEqual ( to: 3 / 5 ) )
195+ #expect( gradient. 1 [ 0 ] . isApproximatelyEqual ( to: 4 / 5 ) )
191196 }
192197
193198 @Test ( . disabled( " derivative not implemented " ) )
194199 func testGamma( ) {
195200 let vwpb = valueWithPullback ( at: SIMD32 < Double > ( repeating: 2 ) , of: SIMD32< Double> . gamma)
196- #expect( vwpb. value == . init ( repeating : 1 ) )
197- #expect( vwpb. pullback ( . one) == . init ( repeating : 0 ) )
201+ #expect( vwpb. value [ 0 ] . isApproximatelyEqual ( to : 1 ) )
202+ #expect( vwpb. pullback ( . one) [ 0 ] . isApproximatelyEqual ( to : 0 , absoluteTolerance : . ulpOfOne ) )
198203 }
199204
200205 @Test
201206 func testLog2( ) {
202207 let vwpb = valueWithPullback ( at: SIMD64 < Double > ( repeating: 2 ) , of: SIMD64< Double> . log2)
203- #expect( vwpb. value == . init ( repeating : 1 ) )
204- #expect( vwpb. pullback ( . one) == . init ( repeating : 1 / . log( 4 ) ) )
208+ #expect( vwpb. value [ 0 ] . isApproximatelyEqual ( to : 1 ) )
209+ #expect( vwpb. pullback ( . one) [ 0 ] . isApproximatelyEqual ( to : 1 / . log( 4 ) ) )
205210 }
206211
207212 @Test
208213 func testLog10( ) {
209214 let vwpb = valueWithPullback ( at: 2.0 , of: Float . log10)
210- #expect( vwpb. value == 0.30103 ) // .log(2) / .log(10)
211- #expect( vwpb. pullback ( 1 ) == 1 / . log( 100 ) )
215+ #expect( vwpb. value. isApproximatelyEqual ( to : . log( 2 ) / . log( 10 ) ) )
216+ #expect( vwpb. pullback ( 1 ) . isApproximatelyEqual ( to : 1 / . log( 100 ) ) )
212217 }
213218
214219 @Test ( . disabled( " derivative not implemented " ) )
215220 func testLogGamma( ) {
216221 let vwpb = valueWithPullback ( at: 2 , of: Double . logGamma)
217- #expect( vwpb. value == 0 )
218- #expect( vwpb. pullback ( 1 ) == 0 )
222+ #expect( vwpb. value. isApproximatelyEqual ( to : 0 ) )
223+ #expect( vwpb. pullback ( 1 ) . isApproximatelyEqual ( to : 0 , absoluteTolerance : . ulpOfOne ) )
219224 }
220225
221226 @Test
222227 func testAbs( ) {
223228 let vwpb = valueWithPullback ( at: SIMD2 < Float > ( repeating: - 2 ) , of: SIMD2< Float> . abs)
224- #expect( vwpb. value == . init ( repeating : 2 ) )
225- #expect( vwpb. pullback ( . one) == . init ( repeating : - 1 ) )
229+ #expect( vwpb. value [ 0 ] . isApproximatelyEqual ( to : 2 ) )
230+ #expect( vwpb. pullback ( . one) [ 0 ] . isApproximatelyEqual ( to : - 1 ) )
226231 }
227232}
0 commit comments