nmatrix-gemv 0.0.3

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.
Files changed (56) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +29 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +14 -0
  5. data/Gemfile +7 -0
  6. data/README.md +29 -0
  7. data/Rakefile +225 -0
  8. data/ext/nmatrix_gemv/binary_format.txt +53 -0
  9. data/ext/nmatrix_gemv/data/complex.h +399 -0
  10. data/ext/nmatrix_gemv/data/data.cpp +298 -0
  11. data/ext/nmatrix_gemv/data/data.h +771 -0
  12. data/ext/nmatrix_gemv/data/meta.h +70 -0
  13. data/ext/nmatrix_gemv/data/rational.h +436 -0
  14. data/ext/nmatrix_gemv/data/ruby_object.h +471 -0
  15. data/ext/nmatrix_gemv/extconf.rb +254 -0
  16. data/ext/nmatrix_gemv/math.cpp +1639 -0
  17. data/ext/nmatrix_gemv/math/asum.h +143 -0
  18. data/ext/nmatrix_gemv/math/geev.h +82 -0
  19. data/ext/nmatrix_gemv/math/gemm.h +271 -0
  20. data/ext/nmatrix_gemv/math/gemv.h +212 -0
  21. data/ext/nmatrix_gemv/math/ger.h +96 -0
  22. data/ext/nmatrix_gemv/math/gesdd.h +80 -0
  23. data/ext/nmatrix_gemv/math/gesvd.h +78 -0
  24. data/ext/nmatrix_gemv/math/getf2.h +86 -0
  25. data/ext/nmatrix_gemv/math/getrf.h +240 -0
  26. data/ext/nmatrix_gemv/math/getri.h +108 -0
  27. data/ext/nmatrix_gemv/math/getrs.h +129 -0
  28. data/ext/nmatrix_gemv/math/idamax.h +86 -0
  29. data/ext/nmatrix_gemv/math/inc.h +47 -0
  30. data/ext/nmatrix_gemv/math/laswp.h +165 -0
  31. data/ext/nmatrix_gemv/math/long_dtype.h +52 -0
  32. data/ext/nmatrix_gemv/math/math.h +1069 -0
  33. data/ext/nmatrix_gemv/math/nrm2.h +181 -0
  34. data/ext/nmatrix_gemv/math/potrs.h +129 -0
  35. data/ext/nmatrix_gemv/math/rot.h +141 -0
  36. data/ext/nmatrix_gemv/math/rotg.h +115 -0
  37. data/ext/nmatrix_gemv/math/scal.h +73 -0
  38. data/ext/nmatrix_gemv/math/swap.h +73 -0
  39. data/ext/nmatrix_gemv/math/trsm.h +387 -0
  40. data/ext/nmatrix_gemv/nm_memory.h +60 -0
  41. data/ext/nmatrix_gemv/nmatrix_gemv.cpp +90 -0
  42. data/ext/nmatrix_gemv/nmatrix_gemv.h +374 -0
  43. data/ext/nmatrix_gemv/ruby_constants.cpp +153 -0
  44. data/ext/nmatrix_gemv/ruby_constants.h +107 -0
  45. data/ext/nmatrix_gemv/ruby_nmatrix.c +84 -0
  46. data/ext/nmatrix_gemv/ttable_helper.rb +122 -0
  47. data/ext/nmatrix_gemv/types.h +54 -0
  48. data/ext/nmatrix_gemv/util/util.h +78 -0
  49. data/lib/nmatrix-gemv.rb +43 -0
  50. data/lib/nmatrix_gemv/blas.rb +85 -0
  51. data/lib/nmatrix_gemv/nmatrix_gemv.rb +35 -0
  52. data/lib/nmatrix_gemv/rspec.rb +75 -0
  53. data/nmatrix-gemv.gemspec +31 -0
  54. data/spec/blas_spec.rb +154 -0
  55. data/spec/spec_helper.rb +128 -0
  56. metadata +186 -0
@@ -0,0 +1,70 @@
1
+ /////////////////////////////////////////////////////////////////////
2
+ // = NMatrix
3
+ //
4
+ // A linear algebra library for scientific computation in Ruby.
5
+ // NMatrix is part of SciRuby.
6
+ //
7
+ // NMatrix was originally inspired by and derived from NArray, by
8
+ // Masahiro Tanaka: http://narray.rubyforge.org
9
+ //
10
+ // == Copyright Information
11
+ //
12
+ // SciRuby is Copyright (c) 2010 - 2014, Ruby Science Foundation
13
+ // NMatrix is Copyright (c) 2012 - 2014, John Woods and the Ruby Science Foundation
14
+ //
15
+ // Please see LICENSE.txt for additional copyright notices.
16
+ //
17
+ // == Contributing
18
+ //
19
+ // By contributing source code to SciRuby, you agree to be bound by
20
+ // our Contributor Agreement:
21
+ //
22
+ // * https://github.com/SciRuby/sciruby/wiki/Contributor-Agreement
23
+ //
24
+ // == meta.h
25
+ //
26
+ // Header file for dealing with template metaprogramming.
27
+
28
+ #ifndef META_H
29
+ # define META_H
30
+
31
+ namespace nm {
32
+ /*
33
+ * Template Metaprogramming
34
+ */
35
+ template <typename T> struct ctype_to_dtype_enum {
36
+ static const nm::dtype_t value_type = nm::BYTE;
37
+ };
38
+ template <> struct ctype_to_dtype_enum<uint8_t> { static const nm::dtype_t value_type = nm::BYTE; };
39
+ template <> struct ctype_to_dtype_enum<int8_t> { static const nm::dtype_t value_type = nm::INT8; };
40
+ template <> struct ctype_to_dtype_enum<int16_t> { static const nm::dtype_t value_type = nm::INT16; };
41
+ template <> struct ctype_to_dtype_enum<int32_t> { static const nm::dtype_t value_type = nm::INT32; };
42
+ template <> struct ctype_to_dtype_enum<int64_t> { static const nm::dtype_t value_type = nm::INT64; };
43
+ template <> struct ctype_to_dtype_enum<float> { static const nm::dtype_t value_type = nm::FLOAT32; };
44
+ template <> struct ctype_to_dtype_enum<double> { static const nm::dtype_t value_type = nm::FLOAT64; };
45
+ template <> struct ctype_to_dtype_enum<Complex64> { static const nm::dtype_t value_type = nm::COMPLEX64; };
46
+ template <> struct ctype_to_dtype_enum<Complex128> { static const nm::dtype_t value_type = nm::COMPLEX128; };
47
+ template <> struct ctype_to_dtype_enum<Rational32> { static const nm::dtype_t value_type = nm::RATIONAL32; };
48
+ template <> struct ctype_to_dtype_enum<Rational64> { static const nm::dtype_t value_type = nm::RATIONAL64; };
49
+ template <> struct ctype_to_dtype_enum<Rational128> { static const nm::dtype_t value_type = nm::RATIONAL128; };
50
+ template <> struct ctype_to_dtype_enum<RubyObject> { static const nm::dtype_t value_type = nm::RUBYOBJ; };
51
+
52
+
53
+ template <nm::dtype_t Enum> struct dtype_enum_T;
54
+ template <> struct dtype_enum_T<nm::BYTE> { typedef uint8_t type; };
55
+ template <> struct dtype_enum_T<nm::INT8> { typedef int8_t type; };
56
+ template <> struct dtype_enum_T<nm::INT16> { typedef int16_t type; };
57
+ template <> struct dtype_enum_T<nm::INT32> { typedef int32_t type; };
58
+ template <> struct dtype_enum_T<nm::INT64> { typedef int64_t type; };
59
+ template <> struct dtype_enum_T<nm::FLOAT32> { typedef float type; };
60
+ template <> struct dtype_enum_T<nm::FLOAT64> { typedef double type; };
61
+ template <> struct dtype_enum_T<nm::COMPLEX64> { typedef nm::Complex64 type; };
62
+ template <> struct dtype_enum_T<nm::COMPLEX128> { typedef nm::Complex128 type; };
63
+ template <> struct dtype_enum_T<nm::RATIONAL32> { typedef nm::Rational32 type; };
64
+ template <> struct dtype_enum_T<nm::RATIONAL64> { typedef nm::Rational64 type; };
65
+ template <> struct dtype_enum_T<nm::RATIONAL128> { typedef nm::Rational128 type; };
66
+ template <> struct dtype_enum_T<nm::RUBYOBJ> { typedef nm::RubyObject type; };
67
+
68
+ } // end namespace nm
69
+
70
+ #endif
@@ -0,0 +1,436 @@
1
+ /////////////////////////////////////////////////////////////////////
2
+ // = NMatrix
3
+ //
4
+ // A linear algebra library for scientific computation in Ruby.
5
+ // NMatrix is part of SciRuby.
6
+ //
7
+ // NMatrix was originally inspired by and derived from NArray, by
8
+ // Masahiro Tanaka: http://narray.rubyforge.org
9
+ //
10
+ // == Copyright Information
11
+ //
12
+ // SciRuby is Copyright (c) 2010 - 2014, Ruby Science Foundation
13
+ // NMatrix is Copyright (c) 2012 - 2014, John Woods and the Ruby Science Foundation
14
+ //
15
+ // Please see LICENSE.txt for additional copyright notices.
16
+ //
17
+ // == Contributing
18
+ //
19
+ // By contributing source code to SciRuby, you agree to be bound by
20
+ // our Contributor Agreement:
21
+ //
22
+ // * https://github.com/SciRuby/sciruby/wiki/Contributor-Agreement
23
+ //
24
+ // == rational.h
25
+ //
26
+ // Functions and classes for dealing with rational numbers.
27
+
28
+ #ifndef RATIONAL_H
29
+ #define RATIONAL_H
30
+
31
+ /*
32
+ * Standard Includes
33
+ */
34
+
35
+ #include <type_traits>
36
+ #include <ruby.h>
37
+ #include <iostream>
38
+
39
+ /*
40
+ * Project Includes
41
+ */
42
+
43
+ #include "types.h"
44
+
45
+ #include "util/util.h"
46
+
47
+ /*
48
+ * Macros
49
+ */
50
+
51
+ /*
52
+ * Types
53
+ */
54
+
55
+ namespace nm {
56
+
57
+ template <typename Type> class Rational;
58
+
59
+ typedef Rational<int16_t> Rational32;
60
+ typedef Rational<int32_t> Rational64;
61
+ typedef Rational<int64_t> Rational128;
62
+
63
+ /*
64
+ * Data
65
+ */
66
+
67
+ /*
68
+ * Classes and Functions
69
+ */
70
+
71
+ template <typename Type>
72
+ class Rational {
73
+ public:
74
+ // The numerator and denominator of the rational number.
75
+ Type n;
76
+ Type d;
77
+
78
+ /*
79
+ * Default constructor.
80
+ */
81
+ inline Rational(Type num = 0, Type den = 1) : n(num), d(den) {}
82
+
83
+ /*
84
+ * Copy constructors.
85
+ */
86
+ template <typename OtherType>
87
+ inline Rational(const Rational<OtherType>& other) : n(other.n), d(other.d) {}
88
+
89
+ template <typename FloatType, typename = typename std::enable_if<std::is_floating_point<FloatType>::value>::type>
90
+ inline Rational(const Complex<FloatType>& other) : n(0), d(1) {
91
+ rb_raise(rb_eNotImpError, "cannot convert from complex to rational");
92
+ }
93
+
94
+ Rational(const RubyObject& other);
95
+
96
+ /*
97
+ * Rational inverse function -- creates a copy, but inverted.
98
+ */
99
+ inline Rational<Type> inverse() const {
100
+ return Rational<Type>(this->d, this->n);
101
+ }
102
+
103
+ /*
104
+ * Binary operator definitions for varous types.
105
+ */
106
+
107
+ //////////////////////////////////
108
+ // Rational-Rational Operations //
109
+ //////////////////////////////////
110
+
111
+ template <typename OtherType>
112
+ inline Rational<Type> operator+(const Rational<OtherType>& other) const {
113
+ Rational<Type> result((this->n * other.d) + (other.n * this->d), this->d * other.d);
114
+
115
+ long simplify = gcf<Type>(result.n, result.d);
116
+
117
+ result.n /= simplify;
118
+ result.d /= simplify;
119
+
120
+ return result;
121
+ }
122
+
123
+ template <typename OtherType>
124
+ inline Rational<Type>& operator+=(const Rational<OtherType>& other) {
125
+ this->n = (this->n * other.d) + (other.n * this->d);
126
+ this->d = this->d * other.d;
127
+
128
+ long simplify = gcf<Type>(this->n, this->d);
129
+
130
+ this->n /= simplify;
131
+ this->d /= simplify;
132
+
133
+ return *this;
134
+ }
135
+
136
+ template <typename OtherType>
137
+ inline Rational<Type> operator-(const Rational<OtherType>& other) const {
138
+ Rational<Type> result((this->n * other.d) - (other.n * this->d), this->d * other.d);
139
+
140
+ long simplify = gcf<Type>(result.n, result.d);
141
+
142
+ result.n /= simplify;
143
+ result.d /= simplify;
144
+
145
+ return result;
146
+ }
147
+
148
+ template <typename OtherType>
149
+ inline Rational<Type>& operator-=(const Rational<OtherType>& other) {
150
+ this->n = (this->n * other.d) - (other.n * this->d);
151
+ this->d = this->d * other.d;
152
+
153
+ long simplify = gcf<Type>(this->n, this->d);
154
+
155
+ this->n /= simplify;
156
+ this->d /= simplify;
157
+
158
+ return *this;
159
+ }
160
+
161
+ template <typename OtherType>
162
+ inline Rational<Type> operator*(const Rational<OtherType>& other) const {
163
+ int g1 = gcf<Type>(this->n, other.d);
164
+ int g2 = gcf<Type>(this->d, other.n);
165
+
166
+ return Rational<Type>((this->n / g1) * (other.n / g2), (this->d / g2) * (other.d / g1));
167
+ }
168
+
169
+
170
+ template <typename OtherType>
171
+ inline Rational<Type>& operator*=(const Rational<OtherType>& other) {
172
+ int g1 = gcf<Type>(this->n, other.d);
173
+ int g2 = gcf<Type>(this->d, other.n);
174
+
175
+ this->n = (this->n / g1) * (other.n / g2);
176
+ this->d = (this->d / g2) * (other.d / g1);
177
+
178
+ return *this;
179
+ }
180
+
181
+
182
+ template <typename OtherType>
183
+ inline Rational<Type> operator/(const Rational<OtherType>& other) const {
184
+ return *this * Rational<OtherType>(other.d, other.n);
185
+ }
186
+
187
+ template <typename OtherType>
188
+ inline Rational<Type> operator/=(const Rational<OtherType>& other) {
189
+ *this *= Rational<OtherType>(other.d, other.n);
190
+ return *this;
191
+ }
192
+
193
+ template <typename OtherType>
194
+ inline Rational<Type> operator%(const Rational<OtherType>& other) const {
195
+ long floor_div = (this->n * other.n) / (this->d * other.d);
196
+ Rational<Type> prod = other * Rational<long>(floor_div, 1);
197
+
198
+ return Rational<long>(this->n, other.n) - prod;
199
+ }
200
+
201
+ template <typename OtherType>
202
+ inline bool operator<(const Rational<OtherType>& other) const {
203
+ return (this->n * other.d) < (other.n * this->d);
204
+ }
205
+
206
+ template <typename OtherType>
207
+ inline bool operator>(const Rational<OtherType>& other) const {
208
+ return (this->n * other.d) > (other.n * this->d);
209
+ }
210
+
211
+ template <typename OtherType>
212
+ inline bool operator==(const Rational<OtherType>& other) const {
213
+ return (this->n == other.n) && (this->d == other.d);
214
+ }
215
+
216
+ template <typename OtherType>
217
+ inline bool operator!=(const Rational<OtherType>& other) const {
218
+ return !(*this == other);
219
+ }
220
+
221
+ template <typename OtherType>
222
+ inline bool operator<=(const Rational<OtherType>& other) const {
223
+ return (*this < other) || (*this == other);
224
+ }
225
+
226
+ template <typename OtherType>
227
+ inline bool operator>=(const Rational<OtherType>& other) const {
228
+ return (*this > other) || (*this == other);
229
+ }
230
+
231
+ template <typename OtherType>
232
+ inline operator Rational<OtherType> () const {
233
+ return Rational<OtherType>((OtherType)this->n, (OtherType)this->d);
234
+ }
235
+
236
+ ////////////////////////////////
237
+ // Rational-Native Operations //
238
+ ////////////////////////////////
239
+
240
+ template <typename IntType, typename = typename std::enable_if<std::is_integral<IntType>::value>::type>
241
+ inline Rational<Type> operator+(const IntType& other) const {
242
+ return *this + Rational<Type>(other);
243
+ }
244
+
245
+ template <typename IntType, typename = typename std::enable_if<std::is_integral<IntType>::value>::type>
246
+ inline Rational<Type> operator-(const IntType& other) const {
247
+ return *this - Rational<Type>(other);
248
+ }
249
+
250
+ template <typename IntType, typename = typename std::enable_if<std::is_integral<IntType>::value>::type>
251
+ inline Rational<Type> operator*(const IntType& other) const {
252
+ return *this * Rational<Type>(other);
253
+ }
254
+
255
+ template <typename IntType, typename = typename std::enable_if<std::is_integral<IntType>::value>::type>
256
+ inline Rational<Type> operator/(const IntType& other) const {
257
+ return *this / Rational<Type>(other);
258
+ }
259
+
260
+ template <typename IntType, typename = typename std::enable_if<std::is_integral<IntType>::value>::type>
261
+ inline Rational<Type> operator%(const IntType& other) const {
262
+ return *this % Rational<Type>(other);
263
+ }
264
+
265
+ template <typename IntType, typename = typename std::enable_if<std::is_integral<IntType>::value>::type>
266
+ inline bool operator<(const IntType& other) const {
267
+ return *this < Rational<Type>(other);
268
+ }
269
+
270
+ template <typename IntType, typename = typename std::enable_if<std::is_integral<IntType>::value>::type>
271
+ inline bool operator>(const IntType& other) const {
272
+ return *this > Rational<Type>(other);
273
+ }
274
+
275
+ template <typename IntType, typename = typename std::enable_if<std::is_integral<IntType>::value>::type>
276
+ inline bool operator==(const IntType& other) const {
277
+ return *this == Rational<Type>(other);
278
+ }
279
+
280
+ template <typename IntType, typename = typename std::enable_if<std::is_integral<IntType>::value>::type>
281
+ inline bool operator!=(const IntType& other) const {
282
+ return *this != Rational<Type>(other);
283
+ }
284
+
285
+ template <typename IntType, typename = typename std::enable_if<std::is_integral<IntType>::value>::type>
286
+ inline bool operator<=(const IntType& other) const {
287
+ return *this <= Rational<Type>(other);
288
+ }
289
+
290
+ template <typename IntType, typename = typename std::enable_if<std::is_integral<IntType>::value>::type>
291
+ inline bool operator>=(const IntType& other) const {
292
+ return *this >= Rational<Type>(other);
293
+ }
294
+
295
+ template <typename NumType, typename = typename std::enable_if<std::is_arithmetic<NumType>::value>::type>
296
+ inline operator NumType () const {
297
+ return (NumType)this->n / (NumType)this->d;
298
+ }
299
+
300
+ /*
301
+ * Special casting operator for Complex numbers.
302
+ */
303
+ template <typename FloatType, typename = typename std::enable_if<std::is_floating_point<FloatType>::value>::type>
304
+ inline operator Rational<FloatType> () const {
305
+ return Rational<FloatType>(((FloatType)this->n) / ((FloatType)this->d));
306
+ }
307
+ };
308
+
309
+ // Negative operator
310
+ template <typename Type, typename = typename std::enable_if<std::is_integral<Type>::value>::type>
311
+ inline Rational<Type> operator-(const Rational<Type>& rhs) {
312
+ return Rational<Type>(-rhs.n, rhs.d);
313
+ }
314
+
315
+ ////////////////////////////////
316
+ // Native-Rational Operations //
317
+ ////////////////////////////////
318
+
319
+ /*
320
+ * Integer Math
321
+ */
322
+
323
+ template <typename IntType, typename RationalType, typename = typename std::enable_if<std::is_integral<IntType>::value>::type>
324
+ inline Rational<RationalType> operator+(const IntType& left, const Rational<RationalType>& right) {
325
+ return Rational<RationalType>(left) + right;
326
+ }
327
+
328
+ template <typename IntType, typename RationalType, typename = typename std::enable_if<std::is_integral<IntType>::value>::type>
329
+ inline Rational<RationalType> operator-(const IntType& left, const Rational<RationalType>& right) {
330
+ return Rational<RationalType>(left) - right;
331
+ }
332
+
333
+ template <typename IntType, typename RationalType, typename = typename std::enable_if<std::is_integral<IntType>::value>::type>
334
+ inline Rational<RationalType> operator*(const IntType& left, const Rational<RationalType>& right) {
335
+ return Rational<RationalType>(left) * right;
336
+ }
337
+
338
+ template <typename IntType, typename RationalType, typename = typename std::enable_if<std::is_integral<IntType>::value>::type>
339
+ inline Rational<RationalType> operator/(const IntType& left, const Rational<RationalType>& right) {
340
+ return Rational<RationalType>(left) / right;
341
+ }
342
+
343
+ /*
344
+ * Floating Point Math
345
+ */
346
+
347
+ template <typename FloatType, typename RationalType, typename = typename std::enable_if<std::is_floating_point<FloatType>::value>::type>
348
+ inline FloatType operator+(const FloatType& left, const Rational<RationalType>& right) {
349
+ return left + (FloatType)right;
350
+ }
351
+
352
+ template <typename FloatType, typename RationalType, typename = typename std::enable_if<std::is_floating_point<FloatType>::value>::type>
353
+ inline FloatType operator-(const FloatType& left, const Rational<RationalType>& right) {
354
+ return left - (FloatType)right;
355
+ }
356
+
357
+ template <typename FloatType, typename RationalType, typename = typename std::enable_if<std::is_floating_point<FloatType>::value>::type>
358
+ inline FloatType operator*(const FloatType& left, const Rational<RationalType>& right) {
359
+ return left * (FloatType)right;
360
+ }
361
+
362
+ template <typename FloatType, typename RationalType, typename = typename std::enable_if<std::is_floating_point<FloatType>::value>::type>
363
+ inline FloatType operator/(const FloatType& left, const Rational<RationalType>& right) {
364
+ return left / (FloatType)right;
365
+ }
366
+
367
+ /*
368
+ * Comparisons
369
+ */
370
+
371
+ template <typename NativeType, typename RationalType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
372
+ inline bool operator<(const NativeType left, const Rational<RationalType>& right) {
373
+ //return Rational<RationalType>(left) < right;
374
+ return (left * right.d) < right.n;
375
+ }
376
+
377
+ template <typename NativeType, typename RationalType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
378
+ inline bool operator>(const NativeType left, const Rational<RationalType>& right) {
379
+ //return Rational<RationalType>(left) > right;
380
+ return (left * right.d) > right.n;
381
+ }
382
+
383
+ template <typename IntType, typename RationalType>
384
+ inline bool operator==(const typename std::enable_if<std::is_integral<IntType>::value, IntType>::type left, const Rational<RationalType>& right) {
385
+ //return Rational<RationalType>(left) == right;
386
+ return (left * right.d) == right.n;
387
+ }
388
+
389
+ template <typename FloatType, typename RationalType>
390
+ inline bool operator==(const typename std::enable_if<std::is_floating_point<FloatType>::value, FloatType>::type left, const Rational<RationalType>& right) {
391
+ //return Rational<RationalType>(left) == right;
392
+ return FP_EQUAL(left, ((FloatType)right));
393
+ }
394
+
395
+ template <typename NativeType, typename RationalType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
396
+ inline bool operator!=(const NativeType left, const Rational<RationalType>& right) {
397
+ //return Rational<RationalType>(left) != right;
398
+ return !(left == right);
399
+ }
400
+
401
+ template <typename NativeType, typename RationalType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
402
+ inline bool operator<=(const NativeType left, const Rational<RationalType>& right) {
403
+ //return Rational<RationalType>(left) <= right;
404
+ return (left < right) or (left == right);
405
+ }
406
+
407
+ template <typename NativeType, typename RationalType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
408
+ inline bool operator>=(const NativeType left, const Rational<RationalType>& right) {
409
+ //return Rational<RationalType>(left) >= right;
410
+ return (left > right) or (left == right);
411
+ }
412
+
413
+ template <typename Type>
414
+ inline std::ostream& operator<<(std::ostream& out, const Rational<Type>& rhs) {
415
+ out << rhs.n << "/" << rhs.d << std::flush;
416
+ return out;
417
+ }
418
+
419
+ } // end of namespace nm
420
+
421
+ namespace std {
422
+ template <typename IntType, typename = typename std::enable_if<std::is_integral<IntType>::value>::type>
423
+ nm::Rational<IntType> abs(const nm::Rational<IntType>& value) {
424
+ if (value.n >= 0) return value;
425
+ return nm::Rational<IntType>(-value.n, value.d);
426
+ }
427
+
428
+ template <typename IntType, typename = typename std::enable_if<std::is_integral<IntType>::value>::type>
429
+ nm::Rational<IntType> sqrt(const nm::Rational<IntType>& value) {
430
+ nm::Rational<IntType> result(std::sqrt(value.n), std::sqrt(value.d));
431
+ if (value * value == result) return result;
432
+ else rb_raise(rb_eArgError, "square root of the given rational is not rational");
433
+ }
434
+ }
435
+
436
+ #endif // RATIONAL_H