-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathunit_circle_ODE.m
141 lines (125 loc) · 3.75 KB
/
unit_circle_ODE.m
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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
% Test for the unit circle on p. 51 of
% The Princeton Companion to Applied Mathematics,
% Princeton University Press, 2015.
% Clear chop options and reset PRNG seed
clear all
rng(500)
% Steps of ODE integration
N = 512;
% Set up data sampling period
sampling_period = 10;
% Get the coordinates of the exact solution
h_dp = 2*pi/300;
for i=1:301
coordinates_exact(i, :) = [cos((i-1)*h_dp), -sin((i-1)*h_dp)];
end
coordinates = [];
global precision
options.round = 1; % RN
% Run two cases: with RN and with SR.
for k = 1:2
switch k
case 1, options.format = 'fp16'; options.subnormal = 1; sr = 0;
case 2, options.format = 'fp16'; options.subnormal = 1; sr = 1;
precision = 10;
end
fprintf('k = %1.0f, prec = %s, subnormal = %1.0f\n',...
k,options.format,options.subnormal)
chop([],options)
% Initial values
u_fp = chop(1);
v_fp = chop(0);
% Timestep size
x_fp = chop(0);
h_fp = chop(2*pi/N, options);
j=0;
% Solve the unit circle
for i=1:N+1
% Update the coordinates
if (mod(i, sampling_period) == 0)
j = j+1;
coordinates(k, j, :) = [u_fp, v_fp];
end
[u_fp, v_fp] = Euler(0, h_fp, u_fp, v_fp, sr, options);
x_fp = chop(x_fp + h_fp);
options.round = 1;
chop([],options)
end
end
h = plot(...
coordinates(1, :, 1), coordinates(1, :, 2),'-', ...
coordinates(2, :, 1), coordinates(2, :, 2),'--', ...
coordinates_exact(:, 1), coordinates_exact(:, 2),'--k');
xlabel('u')
ylabel('v')
grid
legend('fp16 RN','fp16 SR', ...
'Exact', 'Position', [0.4 0.4 0.1 0.2])
set(h,'LineWidth',1.2)
pbaspect([1 1 1]) % Set the ratio of the axes
xlim([-1.5 2])
ylim([-1.5 2])
function [u, v] = Euler(accurate, h, u_prev, v_prev, SR, options);
if (accurate)
u = u_prev + h*v_prev;
v = v_prev - h*u_prev;
elseif (SR)
u = srSum(u_prev, srMultFMA(h, v_prev, ...
rand(), options), rand(), options);
v = srSum(v_prev, -srMultFMA(h, u_prev, ...
rand(), options), rand(), options);
else
u = chop(u_prev + chop(h * v_prev, options), options);
v = chop(v_prev - chop(h * u_prev, options), options);
end
end
% Augmented multiplication algorithm based on FMA
function [sigma, error] = TwoMultFMA(a, b, options);
sigma = chop(a*b, options);
error = chop(a*b-sigma, options); % NOTE: This is an FMA.
end
% Multiplication with stochastic rounding
function f = srMultFMA(a, b, R, options);
global precision
% Switch to RZ
options.round = 4;
chop([], options);
[sigma, error] = TwoMultFMA(a, b, options);
Es = floor(log2(abs(sigma)));
P = sign(error)*R*2^(Es-precision);
f = chop(chop(error+P)+sigma);
% Switch back to RTN
options.round = 1;
chop([], options);
end
% Augmented summation algorithm
function [sum, error] = TwoSum(a, b, options);
sum = chop(a + b, options);
a_trunc = chop(sum - b);
b_trunc = chop(sum - a_trunc);
a_error = chop(a - a_trunc);
b_error = chop(b - b_trunc);
error = chop(a_error + b_error);
end
% Addition with stochastic rounding
function f = srSum(a, b, R, options);
global precision
% Switch on RN
options.round = 1;
[sum, error] = TwoSum(a, b, options);
% Switch to RZ
options.round = 4;
Es = floor(log2(abs(chop(a+b, options))));
P = sign(error)*R*2^(Es-precision);
% Switch to RD or RU.
if (error >= 0)
options.round = 3;
else
options.round = 2;
end
chop([], options);
f = chop(chop(error+P)+sum);
% Switch back to RN
options.round = 1;
chop([], options);
end