nmatrix-gemv 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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