- Notifications
You must be signed in to change notification settings - Fork 10.5k
/
Copy pathfloating_point.swift.gyb
126 lines (102 loc) · 4.89 KB
/
floating_point.swift.gyb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
// RUN: %target-run-simple-swiftgyb(-Xfrontend -enable-experimental-forward-mode-differentiation)
// REQUIRES: executable_test
#if !(os(Windows) || os(Android)) && (arch(i386) || arch(x86_64))
typealiasTestLiteralType=Float80
#else
typealiasTestLiteralType=Double
#endif
import _Differentiation
import StdlibUnittest
varFloatingPointDerivativeTests=TestSuite("FloatingPointDerivatives")
func expectEqualWithTolerance<T>(_ expected:TestLiteralType, _ actual:T,
ulps allowed:T=3,
file:String= #file, line:UInt= #line
)where T:BinaryFloatingPoint{
if actual ==T(expected) || actual.isNaN && expected.isNaN {
return
}
// Compute error in ulp, compare to tolerance.
letabsoluteError=T(abs(TestLiteralType(actual)- expected))
letulpError= absoluteError / T(expected).ulp
expectTrue(ulpError <= allowed,
"\(actual) != \(expected) as \(T.self)"+
"\n\(ulpError)-ulp error exceeds \(allowed)-ulp tolerance.",
file: file, line: line)
}
%for Self in ['Float', 'Double', 'Float80']:
%if Self == 'Float80':
#if !(os(Windows) || os(Android)) && (arch(i386) || arch(x86_64))
%end
%for Other in ['Float', 'Double', 'Float80']:
%if Other == 'Float80':
#if !(os(Windows) || os(Android)) && (arch(i386) || arch(x86_64))
%end
FloatingPointDerivativeTests.test("${Self}.init(_:${Other})"){
expectEqual(1,gradient(at: ${Other}(4), of: ${Self}.init(_:)))
expectEqual(10,pullback(at: ${Other}(4), of: ${Self}.init(_:))(${Self}(10)))
expectEqual(1,derivative(at: ${Other}(4), of: ${Self}.init(_:)))
expectEqual(10,differential(at: ${Other}(4), of: ${Self}.init(_:))(${Other}(10)))
}
%if Other == 'Float80':
#endif
%end
%end # for Other in ['Float', 'Double', 'Float80']:
FloatingPointDerivativeTests.test("${Self}.+"){
expectEqual((1,1),gradient(at: ${Self}(4), ${Self}(5), of:+))
expectEqual((10,10),pullback(at: ${Self}(4), ${Self}(5), of:+)(${Self}(10)))
expectEqual(2,derivative(at: ${Self}(4), ${Self}(5), of:+))
expectEqual(20,differential(at: ${Self}(4), ${Self}(5), of:+)(${Self}(10), ${Self}(10)))
}
FloatingPointDerivativeTests.test("${Self}.-"){
expectEqual((1,-1),gradient(at: ${Self}(4), ${Self}(5), of:-))
expectEqual((10,-10),pullback(at: ${Self}(4), ${Self}(5), of:-)(${Self}(10)))
expectEqual(0,derivative(at: ${Self}(4), ${Self}(5), of:-))
expectEqual(-5,differential(at: ${Self}(4), ${Self}(5), of:-)(${Self}(5), ${Self}(10)))
}
FloatingPointDerivativeTests.test("${Self}.*"){
expectEqual((5,4),gradient(at: ${Self}(4), ${Self}(5), of:*))
expectEqual((50,40),pullback(at: ${Self}(4), ${Self}(5), of:*)(${Self}(10)))
expectEqual(9,derivative(at: ${Self}(4), ${Self}(5), of:*))
expectEqual(90,differential(at: ${Self}(4), ${Self}(5), of:*)(${Self}(10), ${Self}(10)))
}
FloatingPointDerivativeTests.test("${Self}./"){
do{
let(dx, dy)=gradient(at: ${Self}(4), ${Self}(5), of:/)
expectEqual(0.2, dx)
expectEqual(-0.16, dy)
}
do{
let(dx, dy)=pullback(at: ${Self}(4), ${Self}(5), of:/)(${Self}(10))
expectEqual(2, dx)
expectEqualWithTolerance(-1.6, dy)
}
expectEqualWithTolerance(0.04,derivative(at: ${Self}(4), ${Self}(5), of:/))
expectEqual(90,differential(at: ${Self}(4), ${Self}(5), of:*)(${Self}(10), ${Self}(10)))
}
FloatingPointDerivativeTests.test("${Self}.squareRoot"){
expectEqual(0.5,gradient(at:1, of:{ $0.squareRoot()}))
expectEqual(0.25,gradient(at:4, of:{ $0.squareRoot()}))
}
FloatingPointDerivativeTests.test("${Self}.addingProduct"){
expectEqual((1,2,3),gradient(at: ${Self}(10),3,2, of:{ $0.addingProduct($1, $2)}))
expectEqual((2,4,6),pullback(at: ${Self}(10),3,2, of:{ $0.addingProduct($1, $2)})(2))
}
FloatingPointDerivativeTests.test("${Self}.minimum"){
expectEqual((1.0,0.0),gradient(at: ${Self}(1), ${Self}(2), of:{ ${Self}.minimum($0, $1)}))
expectEqual((1.0,0.0),gradient(at: ${Self}(1), ${Self}(1), of:{ ${Self}.minimum($0, $1)}))
expectEqual((0.0,1.0),gradient(at: ${Self}(2), ${Self}(1), of:{ ${Self}.minimum($0, $1)}))
expectEqual((1.0,0.0),gradient(at: ${Self}(1),.nan, of:{ ${Self}.minimum($0, $1)}))
expectEqual((0.0,1.0),gradient(at:.nan, ${Self}(1), of:{ ${Self}.minimum($0, $1)}))
}
FloatingPointDerivativeTests.test("${Self}.maximum"){
expectEqual((0.0,1.0),gradient(at: ${Self}(1), ${Self}(2), of:{ ${Self}.maximum($0, $1)}))
expectEqual((0.0,1.0),gradient(at: ${Self}(1), ${Self}(1), of:{ ${Self}.maximum($0, $1)}))
expectEqual((1.0,0.0),gradient(at: ${Self}(2), ${Self}(1), of:{ ${Self}.maximum($0, $1)}))
expectEqual((1.0,0.0),gradient(at: ${Self}(1),.nan, of:{ ${Self}.maximum($0, $1)}))
expectEqual((0.0,1.0),gradient(at:.nan, ${Self}(1), of:{ ${Self}.maximum($0, $1)}))
}
%if Self == 'Float80':
#endif
%end
%end # for Self in ['Float', 'Double', 'Float80']:
runAllTests()