crmf 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.yardopts +10 -0
- data/LICENSE +674 -0
- data/README.md +35 -0
- data/crmf.gemspec +29 -0
- data/ext/crlibm-1.0beta4.tar.gz +0 -0
- data/ext/crmf/crmf.c +1966 -0
- data/ext/crmf/crmf.h +29 -0
- data/ext/crmf/crmf.map +7 -0
- data/ext/crmf/extconf.rb +68 -0
- data/lib/crmf/version.rb +4 -0
- data/lib/crmf.rb +19 -0
- data/tests/perf.rb +354 -0
- metadata +57 -0
data/ext/crmf/crmf.h
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#ifndef CRMF_H
|
2
|
+
#define CRMF_H
|
3
|
+
|
4
|
+
#if defined _WIN32 || defined __CYGWIN__
|
5
|
+
#ifdef BUILDING_DLL
|
6
|
+
#ifdef __GNUC__
|
7
|
+
#define CRMF_PUBLIC __attribute__ ((dllexport))
|
8
|
+
#else
|
9
|
+
#define CRMF_PUBLIC __declspec(dllexport) // Note: actually gcc seems to also supports this syntax.
|
10
|
+
#endif
|
11
|
+
#else
|
12
|
+
#ifdef __GNUC__
|
13
|
+
#define CRMF_PUBLIC __attribute__ ((dllimport))
|
14
|
+
#else
|
15
|
+
#define CRMF_PUBLIC __declspec(dllimport) // Note: actually gcc seems to also supports this syntax.
|
16
|
+
#endif
|
17
|
+
#endif
|
18
|
+
#define CRMF_LOCAL
|
19
|
+
#else
|
20
|
+
#if __GNUC__ >= 4
|
21
|
+
#define CRMF_PUBLIC __attribute__ ((visibility ("default")))
|
22
|
+
#define CRMF_LOCAL __attribute__ ((visibility ("hidden")))
|
23
|
+
#else
|
24
|
+
#define CRMF_PUBLIC
|
25
|
+
#define CRMF_LOCAL
|
26
|
+
#endif
|
27
|
+
#endif
|
28
|
+
|
29
|
+
#endif /* CRMF_H */
|
data/ext/crmf/crmf.map
ADDED
data/ext/crmf/extconf.rb
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'mkmf'
|
2
|
+
|
3
|
+
dev = not(not(with_config('dev')))
|
4
|
+
force_llvm = not(not(with_config('clang-compiler')))
|
5
|
+
llvm = ((MakeMakefile::CONFIG['CC'] == 'clang') or force_llvm)
|
6
|
+
|
7
|
+
if dev then
|
8
|
+
puts "dev: #{dev}"
|
9
|
+
puts "llvm: #{llvm}"
|
10
|
+
end
|
11
|
+
|
12
|
+
if force_llvm then
|
13
|
+
MakeMakefile::CONFIG['CC'] = 'clang'
|
14
|
+
MakeMakefile::CONFIG['CXX'] = 'clang++'
|
15
|
+
RbConfig::CONFIG['CC'] = 'clang'
|
16
|
+
RbConfig::CONFIG['CPP'] = 'clang -E'
|
17
|
+
$CFLAGS << ' -fdeclspec -Wno-unknown-warning-option'
|
18
|
+
end
|
19
|
+
|
20
|
+
unless have_library('gmp') then
|
21
|
+
abort("-----\n#{caller[0]}\nCannot find libgmp\nPleas install GNU MP, e.g. sudo apt install libgmp-dev\n-----")
|
22
|
+
end
|
23
|
+
|
24
|
+
unless have_library('mpfr') then
|
25
|
+
abort("-----\n#{caller[0]}\nCannot find libmpfr\nPleas install MPFR, e.g. sudo apt install libmpfr-dev\n-----")
|
26
|
+
end
|
27
|
+
|
28
|
+
ext_dir = File.absolute_path(File.join('..', '..'), __FILE__)
|
29
|
+
crlibm_src = File.join(ext_dir, 'crlibm-1.0beta4')
|
30
|
+
crlibm_archive = crlibm_src + '.tar.gz'
|
31
|
+
crlibm_install_dir = File.join(ext_dir, 'crlibm')
|
32
|
+
crlibm_lib_dir = File.join(crlibm_install_dir, 'lib')
|
33
|
+
crlibm_inc_dir = File.join(crlibm_install_dir, 'include')
|
34
|
+
crlibm_bin_dir = File.join(crlibm_install_dir, 'bin')
|
35
|
+
unless File.directory?(crlibm_install_dir) then
|
36
|
+
cmd = "tar xvf '#{crlibm_archive}' -C '#{ext_dir}'"
|
37
|
+
abort "-----\n#{caller[0]}\nCannot untar CRLIBM.\nCommand: \"#{cmd}\"\n-----" unless system(cmd)
|
38
|
+
Dir.chdir(crlibm_src) do
|
39
|
+
cmd = "./configure --prefix='#{crlibm_install_dir}'#{RUBY_PLATFORM =~ /x86_64/ ? ' --enable-sse2 --enable-double-extended' : ''}"
|
40
|
+
abort "-----\n#{caller[0]}\nCannot configure CRLIBM.\nCommand: \"#{cmd}\"\n-----" unless system(cmd)
|
41
|
+
cmd = "make"
|
42
|
+
abort "-----\n#{caller[0]}\nCannot make CRLIBM.\nCommand: \"#{cmd}\"\n-----" unless system(cmd)
|
43
|
+
cmd = "make -j1 install"
|
44
|
+
abort "-----\n#{caller[0]}\nCannot locally install CRLIBM.\nCommand: \"#{cmd}\"\n-----" unless system(cmd)
|
45
|
+
end
|
46
|
+
cmd = "rm -rf '#{crlibm_src}' '#{crlibm_bin_dir}'"
|
47
|
+
abort "-----\n#{caller[0]}\nCannot cleanup CRLIBM.\nCommand: \"#{cmd}\"\n-----" unless system(cmd)
|
48
|
+
end
|
49
|
+
dir_config('crlibm', crlibm_inc_dir, crlibm_lib_dir)
|
50
|
+
abort("-----\n#{caller[0]}\nCannot find libcrlibm in #{crlibm_lib_dir}\n-----") unless have_library('crlibm')
|
51
|
+
|
52
|
+
append_cflags '-fvisibility=hidden'
|
53
|
+
append_ldflags '-Wl,--version-script=crmf.map'
|
54
|
+
|
55
|
+
if dev then
|
56
|
+
append_cflags '-Wall'
|
57
|
+
append_cflags '-Wextra'
|
58
|
+
append_cflags '-Wno-unused-parameter'
|
59
|
+
end
|
60
|
+
#append_cflags '-Wno-suggest-attribute=format'
|
61
|
+
#append_cflags '-Wno-shift-negative-value'
|
62
|
+
#append_cflags '-Wno-sign-compare'
|
63
|
+
#append_cflags '-Wno-unused-function'
|
64
|
+
|
65
|
+
create_makefile 'crmf/crmf'
|
66
|
+
|
67
|
+
File.write('Makefile', File.read('Makefile').sub(/^V = 0$/, 'V = 1').sub(/^all:\s+\$\(DLLIB\)$/, "all: $(DLLIB)\n\t@cp -vf $< ../../lib/crmf/")) if dev
|
68
|
+
|
data/lib/crmf/version.rb
ADDED
data/lib/crmf.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# Copyright (C) 2022 Théotime Bollengier <theotime.bollengier@ensta-bretagne.fr>
|
2
|
+
#
|
3
|
+
# This file is part of CRMF. <https://gitlab.ensta-bretagne.fr/bollenth/crmf>
|
4
|
+
#
|
5
|
+
# CRMF is free software: you can redistribute it and/or modify it
|
6
|
+
# under the terms of the GNU General Public License as published
|
7
|
+
# by the Free Software Foundation, either version 3 of the License,
|
8
|
+
# or (at your option) any later version.
|
9
|
+
#
|
10
|
+
# CRMF is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
13
|
+
# See the GNU General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU General Public License
|
16
|
+
# along with CRMF. If not, see <https://www.gnu.org/licenses/>.
|
17
|
+
|
18
|
+
require_relative './crmf/crmf'
|
19
|
+
require_relative './crmf/version.rb'
|
data/tests/perf.rb
ADDED
@@ -0,0 +1,354 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require '../lib/crmf.rb'
|
3
|
+
|
4
|
+
def print_time(t)
|
5
|
+
if t >= 3600 then
|
6
|
+
u = 'h'
|
7
|
+
t /= 3600
|
8
|
+
elsif t >= 60 then
|
9
|
+
u = 'm'
|
10
|
+
t /= 60
|
11
|
+
elsif t >= 1 then
|
12
|
+
u = 's '
|
13
|
+
elsif t >= 1e-3 then
|
14
|
+
u = 'ms'
|
15
|
+
t *= 1e3
|
16
|
+
elsif t >= 1e-6 then
|
17
|
+
u = 'µs'
|
18
|
+
t *= 1e6
|
19
|
+
elsif t >= 1e-9 then
|
20
|
+
u = 'ns'
|
21
|
+
t *= 1e9
|
22
|
+
elsif t >= 1e-12 then
|
23
|
+
u = 'ps'
|
24
|
+
t *= 1e12
|
25
|
+
else
|
26
|
+
u = 'fs'
|
27
|
+
t *= 1e15
|
28
|
+
end
|
29
|
+
if t >= 1000 then
|
30
|
+
t = t.round(1)
|
31
|
+
elsif t >= 100 then
|
32
|
+
t = t.round(2)
|
33
|
+
elsif t >= 10 then
|
34
|
+
t = t.round(3)
|
35
|
+
else
|
36
|
+
t = t.round(4)
|
37
|
+
end
|
38
|
+
s = t.to_s
|
39
|
+
bef = s.match(/^(\d+)\./)[1]
|
40
|
+
nbef = bef.length
|
41
|
+
aft = s.match(/.(\d+)$/)[1]
|
42
|
+
naft = aft.length
|
43
|
+
if t >= 1000 then
|
44
|
+
bef = bef.rjust(4)
|
45
|
+
elsif t >= 100 then
|
46
|
+
bef = bef.rjust(3)
|
47
|
+
aft = aft.ljust(2,'0')
|
48
|
+
elsif t >= 10 then
|
49
|
+
bef = bef.rjust(2)
|
50
|
+
aft = aft.ljust(3,'0')
|
51
|
+
else
|
52
|
+
aft = aft.ljust(4,'0')
|
53
|
+
end
|
54
|
+
"#{bef}.#{aft} #{u}"
|
55
|
+
end
|
56
|
+
|
57
|
+
nb_tests = 100000
|
58
|
+
fmin = 0 # -Math::PI/2
|
59
|
+
fmax = 1 # Math::PI/2
|
60
|
+
famp = fmax - fmin
|
61
|
+
f = nb_tests.times.collect{rand()*famp + fmin}
|
62
|
+
|
63
|
+
res_libm = Array.new(nb_tests)
|
64
|
+
res_mpfr = Array.new(nb_tests)
|
65
|
+
res_crlibm = Array.new(nb_tests)
|
66
|
+
|
67
|
+
funcs = [
|
68
|
+
'sin',
|
69
|
+
'cos',
|
70
|
+
'tan',
|
71
|
+
'asin',
|
72
|
+
'acos',
|
73
|
+
'atan',
|
74
|
+
'sinh',
|
75
|
+
'cosh',
|
76
|
+
'exp',
|
77
|
+
'log',
|
78
|
+
'log2',
|
79
|
+
'log10'
|
80
|
+
]
|
81
|
+
|
82
|
+
funcs.each do |m|
|
83
|
+
puts " #{m.capitalize} ".center(80, '-')
|
84
|
+
|
85
|
+
mlibm = Math.method(m.to_sym)
|
86
|
+
mmpfr = Float.method(m.to_sym)
|
87
|
+
mcrlibm = CRMF.method("#{m}_rn".to_sym)
|
88
|
+
|
89
|
+
tik = Time.now
|
90
|
+
nb_tests.times do |i|
|
91
|
+
res_libm[i] = mlibm.call(f[i])
|
92
|
+
end
|
93
|
+
tok = Time.now
|
94
|
+
t_libm = tok - tik
|
95
|
+
puts "libm: #{print_time(t_libm)} (#{print_time(t_libm / nb_tests)}/t)"
|
96
|
+
|
97
|
+
tik = Time.now
|
98
|
+
nb_tests.times do |i|
|
99
|
+
res_mpfr[i] = mmpfr.call(f[i])
|
100
|
+
end
|
101
|
+
tok = Time.now
|
102
|
+
t_mpfr = tok - tik
|
103
|
+
puts "mpfr: #{print_time(t_mpfr)} (#{print_time(t_mpfr / nb_tests)}/t)"
|
104
|
+
|
105
|
+
tik = Time.now
|
106
|
+
nb_tests.times do |i|
|
107
|
+
res_crlibm[i] = mcrlibm.call(f[i])
|
108
|
+
end
|
109
|
+
tok = Time.now
|
110
|
+
t_crlibm = tok - tik
|
111
|
+
puts "crlibm: #{print_time(t_crlibm)} (#{print_time(t_crlibm / nb_tests)}/t)"
|
112
|
+
|
113
|
+
max_diff_pct = 0.0
|
114
|
+
nb_tests.times do |i|
|
115
|
+
next if (not(res_libm[i].finite?) and not(res_mpfr[i].finite?))
|
116
|
+
error_pct = 100.0 * (res_libm[i] - res_mpfr[i]).abs / res_mpfr[i]
|
117
|
+
max_diff_pct = [max_diff_pct, error_pct].max
|
118
|
+
end
|
119
|
+
nb_diff_libm_mpfr = nb_tests.times.count{|i| res_libm[i] != res_mpfr[i]}
|
120
|
+
if nb_diff_libm_mpfr > 0 then
|
121
|
+
estr = ", max error: #{max_diff_pct}%"
|
122
|
+
else
|
123
|
+
estr = ''
|
124
|
+
end
|
125
|
+
puts "libm vs mpfr: #{nb_diff_libm_mpfr}/#{nb_tests} (#{nb_diff_libm_mpfr*100.0/nb_tests}%)#{estr}"
|
126
|
+
nb_diff_crlibm_mpfr = nb_tests.times.count{|i| res_crlibm[i] != res_mpfr[i]}
|
127
|
+
puts "crlibm vs mpfr: #{nb_diff_crlibm_mpfr}/#{nb_tests} (#{nb_diff_crlibm_mpfr*100.0/nb_tests}%)"
|
128
|
+
end
|
129
|
+
|
130
|
+
puts
|
131
|
+
|
132
|
+
nbtm1 = nb_tests - 1
|
133
|
+
|
134
|
+
puts " Add N ".center(80, '-')
|
135
|
+
|
136
|
+
tik = Time.now
|
137
|
+
nb_tests.times do |i|
|
138
|
+
res_libm[i] = f[i] + f[nbtm1-i]
|
139
|
+
end
|
140
|
+
tok = Time.now
|
141
|
+
t_libm = tok - tik
|
142
|
+
puts "libm: #{print_time(t_libm)} (#{print_time(t_libm / nb_tests)}/t)"
|
143
|
+
|
144
|
+
tik = Time.now
|
145
|
+
nb_tests.times do |i|
|
146
|
+
res_mpfr[i] = Float.add(f[i], f[nbtm1-i])
|
147
|
+
end
|
148
|
+
tok = Time.now
|
149
|
+
t_mpfr = tok - tik
|
150
|
+
puts "mpfr: #{print_time(t_mpfr)} (#{print_time(t_mpfr / nb_tests)}/t)"
|
151
|
+
|
152
|
+
tik = Time.now
|
153
|
+
nb_tests.times do |i|
|
154
|
+
res_crlibm[i] = CRMF.add_rn(f[i], f[nbtm1-i])
|
155
|
+
end
|
156
|
+
tok = Time.now
|
157
|
+
t_crlibm = tok - tik
|
158
|
+
puts "crlibm: #{print_time(t_crlibm)} (#{print_time(t_crlibm / nb_tests)}/t)"
|
159
|
+
|
160
|
+
max_diff_pct = 0.0
|
161
|
+
nb_tests.times do |i|
|
162
|
+
next if (not(res_libm[i].finite?) and not(res_mpfr[i].finite?))
|
163
|
+
error_pct = 100.0 * (res_libm[i] - res_mpfr[i]).abs / res_mpfr[i]
|
164
|
+
max_diff_pct = [max_diff_pct, error_pct].max
|
165
|
+
end
|
166
|
+
nb_diff_libm_mpfr = nb_tests.times.count{|i| res_libm[i] != res_mpfr[i]}
|
167
|
+
if nb_diff_libm_mpfr > 0 then
|
168
|
+
estr = ", max error: #{max_diff_pct}%"
|
169
|
+
else
|
170
|
+
estr = ''
|
171
|
+
end
|
172
|
+
puts "libm vs mpfr: #{nb_diff_libm_mpfr}/#{nb_tests} (#{nb_diff_libm_mpfr*100.0/nb_tests}%)#{estr}"
|
173
|
+
|
174
|
+
max_diff_pct = 0.0
|
175
|
+
nb_tests.times do |i|
|
176
|
+
next if (not(res_crlibm[i].finite?) and not(res_mpfr[i].finite?))
|
177
|
+
error_pct = 100.0 * (res_crlibm[i] - res_mpfr[i]).abs / res_mpfr[i]
|
178
|
+
max_diff_pct = [max_diff_pct, error_pct].max
|
179
|
+
end
|
180
|
+
nb_diff_crlibm_mpfr = nb_tests.times.count{|i| res_crlibm[i] != res_mpfr[i]}
|
181
|
+
if nb_diff_crlibm_mpfr > 0 then
|
182
|
+
estr = ", max error: #{max_diff_pct}%"
|
183
|
+
else
|
184
|
+
estr = ''
|
185
|
+
end
|
186
|
+
puts "crlibm vs mpfr: #{nb_diff_crlibm_mpfr}/#{nb_tests} (#{nb_diff_crlibm_mpfr*100.0/nb_tests}%)#{estr}"
|
187
|
+
|
188
|
+
|
189
|
+
puts " Add D ".center(80, '-')
|
190
|
+
|
191
|
+
tik = Time.now
|
192
|
+
nb_tests.times do |i|
|
193
|
+
res_libm[i] = f[i] + f[nbtm1-i]
|
194
|
+
end
|
195
|
+
tok = Time.now
|
196
|
+
t_libm = tok - tik
|
197
|
+
puts "libm: #{print_time(t_libm)} (#{print_time(t_libm / nb_tests)}/t)"
|
198
|
+
|
199
|
+
tik = Time.now
|
200
|
+
nb_tests.times do |i|
|
201
|
+
res_mpfr[i] = Float.add(f[i], f[nbtm1-i], :down)
|
202
|
+
end
|
203
|
+
tok = Time.now
|
204
|
+
t_mpfr = tok - tik
|
205
|
+
puts "mpfr: #{print_time(t_mpfr)} (#{print_time(t_mpfr / nb_tests)}/t)"
|
206
|
+
|
207
|
+
tik = Time.now
|
208
|
+
nb_tests.times do |i|
|
209
|
+
res_crlibm[i] = CRMF.add_rd(f[i], f[nbtm1-i])
|
210
|
+
end
|
211
|
+
tok = Time.now
|
212
|
+
t_crlibm = tok - tik
|
213
|
+
puts "crlibm: #{print_time(t_crlibm)} (#{print_time(t_crlibm / nb_tests)}/t)"
|
214
|
+
|
215
|
+
max_diff_pct = 0.0
|
216
|
+
nb_tests.times do |i|
|
217
|
+
next if (not(res_libm[i].finite?) and not(res_mpfr[i].finite?))
|
218
|
+
error_pct = 100.0 * (res_libm[i] - res_mpfr[i]).abs / res_mpfr[i]
|
219
|
+
max_diff_pct = [max_diff_pct, error_pct].max
|
220
|
+
end
|
221
|
+
nb_diff_libm_mpfr = nb_tests.times.count{|i| res_libm[i] != res_mpfr[i]}
|
222
|
+
if nb_diff_libm_mpfr > 0 then
|
223
|
+
estr = ", max error: #{max_diff_pct}%"
|
224
|
+
else
|
225
|
+
estr = ''
|
226
|
+
end
|
227
|
+
puts "libm vs mpfr: #{nb_diff_libm_mpfr}/#{nb_tests} (#{nb_diff_libm_mpfr*100.0/nb_tests}%)#{estr}"
|
228
|
+
|
229
|
+
max_diff_pct = 0.0
|
230
|
+
nb_tests.times do |i|
|
231
|
+
next if (not(res_crlibm[i].finite?) and not(res_mpfr[i].finite?))
|
232
|
+
error_pct = 100.0 * (res_crlibm[i] - res_mpfr[i]).abs / res_mpfr[i]
|
233
|
+
max_diff_pct = [max_diff_pct, error_pct].max
|
234
|
+
end
|
235
|
+
nb_diff_crlibm_mpfr = nb_tests.times.count{|i| res_crlibm[i] != res_mpfr[i]}
|
236
|
+
if nb_diff_crlibm_mpfr > 0 then
|
237
|
+
estr = ", max error: #{max_diff_pct}%"
|
238
|
+
else
|
239
|
+
estr = ''
|
240
|
+
end
|
241
|
+
puts "crlibm vs mpfr: #{nb_diff_crlibm_mpfr}/#{nb_tests} (#{nb_diff_crlibm_mpfr*100.0/nb_tests}%)#{estr}"
|
242
|
+
|
243
|
+
|
244
|
+
|
245
|
+
puts " Add U ".center(80, '-')
|
246
|
+
|
247
|
+
tik = Time.now
|
248
|
+
nb_tests.times do |i|
|
249
|
+
res_libm[i] = f[i] + f[nbtm1-i]
|
250
|
+
end
|
251
|
+
tok = Time.now
|
252
|
+
t_libm = tok - tik
|
253
|
+
puts "libm: #{print_time(t_libm)} (#{print_time(t_libm / nb_tests)}/t)"
|
254
|
+
|
255
|
+
tik = Time.now
|
256
|
+
nb_tests.times do |i|
|
257
|
+
res_mpfr[i] = Float.add(f[i], f[nbtm1-i], :up)
|
258
|
+
end
|
259
|
+
tok = Time.now
|
260
|
+
t_mpfr = tok - tik
|
261
|
+
puts "mpfr: #{print_time(t_mpfr)} (#{print_time(t_mpfr / nb_tests)}/t)"
|
262
|
+
|
263
|
+
tik = Time.now
|
264
|
+
nb_tests.times do |i|
|
265
|
+
res_crlibm[i] = CRMF.add_ru(f[i], f[nbtm1-i])
|
266
|
+
end
|
267
|
+
tok = Time.now
|
268
|
+
t_crlibm = tok - tik
|
269
|
+
puts "crlibm: #{print_time(t_crlibm)} (#{print_time(t_crlibm / nb_tests)}/t)"
|
270
|
+
|
271
|
+
max_diff_pct = 0.0
|
272
|
+
nb_tests.times do |i|
|
273
|
+
next if (not(res_libm[i].finite?) and not(res_mpfr[i].finite?))
|
274
|
+
error_pct = 100.0 * (res_libm[i] - res_mpfr[i]).abs / res_mpfr[i]
|
275
|
+
max_diff_pct = [max_diff_pct, error_pct].max
|
276
|
+
end
|
277
|
+
nb_diff_libm_mpfr = nb_tests.times.count{|i| res_libm[i] != res_mpfr[i]}
|
278
|
+
if nb_diff_libm_mpfr > 0 then
|
279
|
+
estr = ", max error: #{max_diff_pct}%"
|
280
|
+
else
|
281
|
+
estr = ''
|
282
|
+
end
|
283
|
+
puts "libm vs mpfr: #{nb_diff_libm_mpfr}/#{nb_tests} (#{nb_diff_libm_mpfr*100.0/nb_tests}%)#{estr}"
|
284
|
+
|
285
|
+
max_diff_pct = 0.0
|
286
|
+
nb_tests.times do |i|
|
287
|
+
next if (not(res_crlibm[i].finite?) and not(res_mpfr[i].finite?))
|
288
|
+
error_pct = 100.0 * (res_crlibm[i] - res_mpfr[i]).abs / res_mpfr[i]
|
289
|
+
max_diff_pct = [max_diff_pct, error_pct].max
|
290
|
+
end
|
291
|
+
nb_diff_crlibm_mpfr = nb_tests.times.count{|i| res_crlibm[i] != res_mpfr[i]}
|
292
|
+
if nb_diff_crlibm_mpfr > 0 then
|
293
|
+
estr = ", max error: #{max_diff_pct}%"
|
294
|
+
else
|
295
|
+
estr = ''
|
296
|
+
end
|
297
|
+
puts "crlibm vs mpfr: #{nb_diff_crlibm_mpfr}/#{nb_tests} (#{nb_diff_crlibm_mpfr*100.0/nb_tests}%)#{estr}"
|
298
|
+
|
299
|
+
|
300
|
+
puts " Add Z ".center(80, '-')
|
301
|
+
|
302
|
+
tik = Time.now
|
303
|
+
nb_tests.times do |i|
|
304
|
+
res_libm[i] = f[i] + f[nbtm1-i]
|
305
|
+
end
|
306
|
+
tok = Time.now
|
307
|
+
t_libm = tok - tik
|
308
|
+
puts "libm: #{print_time(t_libm)} (#{print_time(t_libm / nb_tests)}/t)"
|
309
|
+
|
310
|
+
tik = Time.now
|
311
|
+
nb_tests.times do |i|
|
312
|
+
res_mpfr[i] = Float.add(f[i], f[nbtm1-i], :zero)
|
313
|
+
end
|
314
|
+
tok = Time.now
|
315
|
+
t_mpfr = tok - tik
|
316
|
+
puts "mpfr: #{print_time(t_mpfr)} (#{print_time(t_mpfr / nb_tests)}/t)"
|
317
|
+
|
318
|
+
tik = Time.now
|
319
|
+
nb_tests.times do |i|
|
320
|
+
res_crlibm[i] = CRMF.add_rz(f[i], f[nbtm1-i])
|
321
|
+
end
|
322
|
+
tok = Time.now
|
323
|
+
t_crlibm = tok - tik
|
324
|
+
puts "crlibm: #{print_time(t_crlibm)} (#{print_time(t_crlibm / nb_tests)}/t)"
|
325
|
+
|
326
|
+
max_diff_pct = 0.0
|
327
|
+
nb_tests.times do |i|
|
328
|
+
next if (not(res_libm[i].finite?) and not(res_mpfr[i].finite?))
|
329
|
+
error_pct = 100.0 * (res_libm[i] - res_mpfr[i]).abs / res_mpfr[i]
|
330
|
+
max_diff_pct = [max_diff_pct, error_pct].max
|
331
|
+
end
|
332
|
+
nb_diff_libm_mpfr = nb_tests.times.count{|i| res_libm[i] != res_mpfr[i]}
|
333
|
+
if nb_diff_libm_mpfr > 0 then
|
334
|
+
estr = ", max error: #{max_diff_pct}%"
|
335
|
+
else
|
336
|
+
estr = ''
|
337
|
+
end
|
338
|
+
puts "libm vs mpfr: #{nb_diff_libm_mpfr}/#{nb_tests} (#{nb_diff_libm_mpfr*100.0/nb_tests}%)#{estr}"
|
339
|
+
|
340
|
+
max_diff_pct = 0.0
|
341
|
+
nb_tests.times do |i|
|
342
|
+
next if (not(res_crlibm[i].finite?) and not(res_mpfr[i].finite?))
|
343
|
+
error_pct = 100.0 * (res_crlibm[i] - res_mpfr[i]).abs / res_mpfr[i]
|
344
|
+
max_diff_pct = [max_diff_pct, error_pct].max
|
345
|
+
end
|
346
|
+
nb_diff_crlibm_mpfr = nb_tests.times.count{|i| res_crlibm[i] != res_mpfr[i]}
|
347
|
+
if nb_diff_crlibm_mpfr > 0 then
|
348
|
+
estr = ", max error: #{max_diff_pct}%"
|
349
|
+
else
|
350
|
+
estr = ''
|
351
|
+
end
|
352
|
+
puts "crlibm vs mpfr: #{nb_diff_crlibm_mpfr}/#{nb_tests} (#{nb_diff_crlibm_mpfr*100.0/nb_tests}%)#{estr}"
|
353
|
+
|
354
|
+
|
metadata
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: crmf
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Théotime Bollengier
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2022-07-21 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: CRMF is a Ruby C extension which provides correctly rounded math functions
|
14
|
+
for Ruby floats, using MPFR and CRlibm. Provided rounding modes are toward zero,
|
15
|
+
+infinity, -infinity a to nearest even.
|
16
|
+
email: theotime.bollengier@ensta-bretagne.fr
|
17
|
+
executables: []
|
18
|
+
extensions:
|
19
|
+
- ext/crmf/extconf.rb
|
20
|
+
extra_rdoc_files: []
|
21
|
+
files:
|
22
|
+
- ".yardopts"
|
23
|
+
- LICENSE
|
24
|
+
- README.md
|
25
|
+
- crmf.gemspec
|
26
|
+
- ext/crlibm-1.0beta4.tar.gz
|
27
|
+
- ext/crmf/crmf.c
|
28
|
+
- ext/crmf/crmf.h
|
29
|
+
- ext/crmf/crmf.map
|
30
|
+
- ext/crmf/extconf.rb
|
31
|
+
- lib/crmf.rb
|
32
|
+
- lib/crmf/version.rb
|
33
|
+
- tests/perf.rb
|
34
|
+
homepage: https://gitlab.ensta-bretagne.fr/bollenth/crmf
|
35
|
+
licenses:
|
36
|
+
- GPL-3.0+
|
37
|
+
metadata: {}
|
38
|
+
post_install_message:
|
39
|
+
rdoc_options: []
|
40
|
+
require_paths:
|
41
|
+
- lib
|
42
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
47
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: '0'
|
52
|
+
requirements: []
|
53
|
+
rubygems_version: 3.2.3
|
54
|
+
signing_key:
|
55
|
+
specification_version: 4
|
56
|
+
summary: Correctly rounded math functions for Ruby floats
|
57
|
+
test_files: []
|