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.
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
@@ -0,0 +1,7 @@
1
+ CRMF {
2
+ global:
3
+ Init_crmf;
4
+ local:
5
+ *;
6
+ };
7
+
@@ -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
+
@@ -0,0 +1,4 @@
1
+ module CRMF
2
+ # @return [String] CRMF gem version
3
+ VERSION = '0.1.1'
4
+ end
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: []