nmatrix 0.1.0.rc5 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +0 -1
  3. data/Gemfile +0 -2
  4. data/History.txt +39 -4
  5. data/LICENSE.txt +3 -1
  6. data/Manifest.txt +2 -0
  7. data/README.rdoc +6 -14
  8. data/Rakefile +4 -1
  9. data/ext/nmatrix/data/data.cpp +1 -1
  10. data/ext/nmatrix/data/data.h +2 -1
  11. data/ext/nmatrix/data/rational.h +230 -226
  12. data/ext/nmatrix/extconf.rb +7 -4
  13. data/ext/nmatrix/math.cpp +259 -172
  14. data/ext/nmatrix/math/getri.h +2 -2
  15. data/ext/nmatrix/math/math.h +1 -1
  16. data/ext/nmatrix/ruby_constants.cpp +0 -1
  17. data/ext/nmatrix/ruby_nmatrix.c +55 -32
  18. data/ext/nmatrix/storage/dense/dense.cpp +1 -0
  19. data/ext/nmatrix/storage/yale/yale.cpp +12 -14
  20. data/ext/nmatrix/ttable_helper.rb +0 -1
  21. data/lib/nmatrix.rb +5 -0
  22. data/lib/nmatrix/homogeneous.rb +98 -0
  23. data/lib/nmatrix/io/fortran_format.rb +135 -0
  24. data/lib/nmatrix/io/harwell_boeing.rb +220 -0
  25. data/lib/nmatrix/io/market.rb +18 -8
  26. data/lib/nmatrix/io/mat5_reader.rb +16 -111
  27. data/lib/nmatrix/io/mat_reader.rb +3 -5
  28. data/lib/nmatrix/io/point_cloud.rb +27 -28
  29. data/lib/nmatrix/lapack.rb +3 -1
  30. data/lib/nmatrix/math.rb +112 -43
  31. data/lib/nmatrix/monkeys.rb +67 -11
  32. data/lib/nmatrix/nmatrix.rb +56 -33
  33. data/lib/nmatrix/rspec.rb +2 -2
  34. data/lib/nmatrix/shortcuts.rb +42 -25
  35. data/lib/nmatrix/version.rb +4 -4
  36. data/nmatrix.gemspec +4 -3
  37. data/spec/03_nmatrix_monkeys_spec.rb +72 -0
  38. data/spec/blas_spec.rb +4 -0
  39. data/spec/homogeneous_spec.rb +12 -4
  40. data/spec/io/fortran_format_spec.rb +88 -0
  41. data/spec/io/harwell_boeing_spec.rb +98 -0
  42. data/spec/io/test.rua +9 -0
  43. data/spec/math_spec.rb +51 -9
  44. metadata +38 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 101aa626bcac374a9e9d435b01f81ce119df0589
4
- data.tar.gz: 003a943f6e7a84371460c36cf7eec4b6e5edc732
3
+ metadata.gz: 707562a21915c1dd82f64baaf3102ff11c83c1fb
4
+ data.tar.gz: 695cf665b38511084ff5d9d282583a31566dbaed
5
5
  SHA512:
6
- metadata.gz: 8caa3986e557c54d6040e86201537dce92c3db161a27d545059244a4e32b7dab2dd396962d1ac77724dffb499d9076aa6c9637dee688149fae7a072e2a03890e
7
- data.tar.gz: 20fb3e32a7f7d59a02e20435ea80430ddddd20f6d479862ebc52e2dbc180ed17e0c1d35a3d9e7a7d65675ac0d382bed83b43a5cc3a1e9ea1478fbf66ba60dc52
6
+ metadata.gz: afd36e03a78d177fab72efcf967f3cf942408f22de02ca3cf85dd23e527e02fc73c7b9946b782bee13ae2312d07f17cc8b3288d342c435f59093ad03a0dc6f27
7
+ data.tar.gz: f247048abadfa6877951bad30f92534d1172b67b5967b58b325a113fbd77fbcf245db06181723ebeb75e0312b6f8d50d9418c0e0b6f47875d13333ffaae21811
@@ -3,7 +3,6 @@ cache: bundler
3
3
  env:
4
4
  - CPLUS_INCLUDE_PATH=/usr/include/atlas C_INCLUDE_PATH=/usr/include/atlas
5
5
  rvm:
6
- - "1.9.2"
7
6
  - "1.9.3"
8
7
  - "2.0.0"
9
8
  - "2.1.0"
data/Gemfile CHANGED
@@ -1,4 +1,2 @@
1
1
  source 'https://rubygems.org'
2
2
  gemspec
3
-
4
- gem 'packable', ">= 1.3.5" # for Matlab IO
@@ -632,11 +632,46 @@
632
632
 
633
633
  * Fixed Yale #inject behavior (by @yoongkang)
634
634
 
635
- === 0.1.0.rc6 / 2014-08-??
635
+ === 0.1.0 / 2014-12-11
636
636
 
637
- * No major enhancements.
637
+ * 3 major enhancements:
638
+
639
+ * Updated to BSD 3-clause license
640
+
641
+ * Removed Ruby 1.9.2 support; now requires Ruby 1.9.3 or
642
+ higher (by @v0dro)
643
+
644
+ * Added Gauss-Jordan elimination for calculation of
645
+ matrix inverses (by @v0dro)
646
+
647
+ * 6 minor enhancements:
648
+
649
+ * Added trace method for square matrices
650
+
651
+ * Improved Array#to_nm monkey patch so matrices and
652
+ arrays can be interconverted easily, without need for a
653
+ shape argument (by @andrewcsmith)
654
+
655
+ * Added Harwell-Boeing and Fortran matrix format parsers
656
+ (by @v0dro)
657
+
658
+ * Removed soon-to-be-deprecated autoloads and replaced
659
+ with a more robust method (by @duggiefresh)
660
+
661
+ * Updated rake install task to use Bundler's GemHelper
662
+ install task (by @duggiefresh)
663
+
664
+ * Moved packable requirement from Gemfile to gemspec
665
+ (by @andrewcsmith)
666
+
667
+ * 3 bug fixes:
638
668
 
639
- * No minor enhancements.
669
+ * Corrected Ubuntu clapack functionality checking, which
670
+ should fix most functions which rely on the ATLAS
671
+ version of clapack
640
672
 
641
- * No bug fixes.
673
+ * Corrected NMatrix::gesdd workspace request size (by
674
+ @yoongkang)
642
675
 
676
+ * Fixed definition of NMatrix#asum for one-by-one
677
+ matrices (by @andrewcsmith)
@@ -9,7 +9,7 @@ You *must* read the Contributor Agreement before contributing code to the SciRub
9
9
 
10
10
  -----
11
11
 
12
- Copyright (c) 2010 - 2014, Ruby Science Foundation
12
+ Copyright (c) 2010 - 2015, John Woods and the Ruby Science Foundation
13
13
  All rights reserved.
14
14
 
15
15
  Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
@@ -18,4 +18,6 @@ Redistribution and use in source and binary forms, with or without modification,
18
18
 
19
19
  * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
20
20
 
21
+ * Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
22
+
21
23
  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -14,6 +14,8 @@ lib/nmatrix/io/market.rb
14
14
  lib/nmatrix/io/mat5_reader.rb
15
15
  lib/nmatrix/io/mat_reader.rb
16
16
  lib/nmatrix/io/point_cloud.rb
17
+ lib/nmatrix/io/fortran_format.rb
18
+ lib/nmatrix/io/harwell_boeing.rb
17
19
  lib/nmatrix/blas.rb
18
20
  lib/nmatrix/enumerate.rb
19
21
  lib/nmatrix/homogeneous.rb
@@ -31,7 +31,7 @@ However, you will need to install {ATLAS}[http://math-atlas.sourceforge.net/] wi
31
31
 
32
32
  * ATLAS, preferably with CLAPACK ({see here for details}[https://github.com/SciRuby/nmatrix/wiki/Installation])
33
33
  * a version of GCC or clang which supports C++0x or C++11
34
- * Ruby 1.9.2+
34
+ * Ruby 1.9.3+
35
35
  * {packable}[http://github.com/marcandre/packable] 1.3.5 (used for I/O)
36
36
 
37
37
  If you want to obtain the latest (development) code, you should generally do:
@@ -104,6 +104,7 @@ The following features exist in the current version of NMatrix (0.1.0.rc1):
104
104
  * Input/output:
105
105
  * Matlab .MAT v5 file input
106
106
  * MatrixMarket file input/output
107
+ * Harwell-Boeing and Fortran file input
107
108
  * Point Cloud Library PCD file input
108
109
  * C and C++ API
109
110
  * BLAS internal implementations (no library) and ATLAS (with library) access:
@@ -122,29 +123,20 @@ The following features exist in the current version of NMatrix (0.1.0.rc1):
122
123
  * xGESVD, xGESDD (singular value decomposition)
123
124
  * xGEEV (eigenvalue decomposition of a asymmetric square matrices)
124
125
  * LU decomposition
125
- * Matrix inversions (requires LAPACK; BLAS dtypes only)
126
+ * Matrix inversions
126
127
  * Determinant calculation for BLAS dtypes
127
- * Vector 2-norms
128
+ * Traces
128
129
  * Ruby/GSL interoperability (requires {SciRuby's fork of rb-gsl}[http://github.com/SciRuby/rb-gsl])
129
130
  * slice assignments, e.g.,
130
131
  x[1..3,0..4] = some_other_matrix
131
132
 
132
133
  === Planned Features (Short-to-Medium Term)
133
134
 
134
- We are nearing the release of NMatrix 0.1.0, our first beta.
135
-
136
- These are features planned for NMatrix 0.2.0:
137
-
138
- * LAPACK-free calculation of determinant, trace, and eigenvalues (characteristic polynomial)
139
- * LAPACK-free matrix inversions
140
- * tensor products
141
- * improved file I/O
142
- * compression of yale symmetries in I/O
143
- * optimization of non-BLAS data types on BLAS-like operations (e.g., matrix multiplication for rational numbers)
135
+ See the issues tracker for a list of planned features or to request new ones.
144
136
 
145
137
  == License
146
138
 
147
- Copyright (c) 2012--14, John Woods and the Ruby Science Foundation.
139
+ Copyright (c) 2012--15, John Woods and the Ruby Science Foundation.
148
140
 
149
141
  All rights reserved.
150
142
 
data/Rakefile CHANGED
@@ -207,7 +207,10 @@ end
207
207
  require "rdoc/task"
208
208
  RDoc::Task.new do |rdoc|
209
209
  rdoc.main = "README.rdoc"
210
- rdoc.rdoc_files.include(%w{README.rdoc History.txt LICENSE.txt CONTRIBUTING.md ext/nmatrix/binary_format.txt lib/nmatrix/**/*.rb ext/nmatrix/**/*.cpp ext/nmatrix/**/*.c ext/nmatrix/**/*.h})
210
+ rdoc.rdoc_files.include(%w{README.rdoc History.txt LICENSE.txt CONTRIBUTING.md lib ext})
211
+ rdoc.options << "--exclude=ext/nmatrix/extconf.rb"
212
+ rdoc.options << "--exclude=ext/nmatrix/ttable_helper.rb"
213
+ rdoc.options << "--exclude=lib/nmatrix/rspec.rb"
211
214
  end
212
215
 
213
216
  # vim: syntax=ruby
@@ -88,7 +88,7 @@ namespace nm {
88
88
  "exp", "log2",
89
89
  "log10", "sqrt", "erf",
90
90
  "erfc", "cbrt", "gamma",
91
- "negate", "floor", "ceil"
91
+ "negate", "floor", "ceil", "round"
92
92
  };
93
93
 
94
94
  } // end of namespace nm
@@ -102,7 +102,8 @@ namespace nm {
102
102
  UNARY_GAMMA,
103
103
  UNARY_NEGATE,
104
104
  UNARY_FLOOR,
105
- UNARY_CEIL
105
+ UNARY_CEIL,
106
+ UNARY_ROUND
106
107
  };
107
108
 
108
109
  // element-wise and scalar operators
@@ -56,9 +56,9 @@ namespace nm {
56
56
 
57
57
  template <typename Type> class Rational;
58
58
 
59
- typedef Rational<int16_t> Rational32;
60
- typedef Rational<int32_t> Rational64;
61
- typedef Rational<int64_t> Rational128;
59
+ typedef Rational<int16_t> Rational32;
60
+ typedef Rational<int32_t> Rational64;
61
+ typedef Rational<int64_t> Rational128;
62
62
 
63
63
  /*
64
64
  * Data
@@ -70,28 +70,28 @@ typedef Rational<int64_t> Rational128;
70
70
 
71
71
  template <typename Type>
72
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);
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
95
 
96
96
  /*
97
97
  * Rational inverse function -- creates a copy, but inverted.
@@ -100,28 +100,28 @@ class Rational {
100
100
  return Rational<Type>(this->d, this->n);
101
101
  }
102
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) {
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
125
  this->n = (this->n * other.d) + (other.n * this->d);
126
126
  this->d = this->d * other.d;
127
127
 
@@ -131,22 +131,22 @@ class Rational {
131
131
  this->d /= simplify;
132
132
 
133
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) {
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
150
  this->n = (this->n * other.d) - (other.n * this->d);
151
151
  this->d = this->d * other.d;
152
152
 
@@ -156,19 +156,29 @@ class Rational {
156
156
  this->d /= simplify;
157
157
 
158
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) {
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
+ template <typename OtherType>
170
+ inline Rational<Type> operator/(const Rational<OtherType>& other) const {
171
+ Rational<Type> result = *this * Rational<OtherType>(other.d, other.n);
172
+
173
+ if (result.d < 0) {
174
+ return Rational<Type>(-result.n, -result.d);
175
+ }
176
+
177
+ return result;
178
+ }
179
+
180
+ template <typename OtherType>
181
+ inline Rational<Type>& operator*=(const Rational<OtherType>& other) {
172
182
  int g1 = gcf<Type>(this->n, other.d);
173
183
  int g2 = gcf<Type>(this->d, other.n);
174
184
 
@@ -176,134 +186,128 @@ class Rational {
176
186
  this->d = (this->d / g2) * (other.d / g1);
177
187
 
178
188
  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
- }
189
+ }
190
+
191
+ template <typename OtherType>
192
+ inline Rational<Type> operator/=(const Rational<OtherType>& other) {
193
+ *this *= Rational<OtherType>(other.d, other.n);
194
+ return *this;
195
+ }
196
+
197
+ template <typename OtherType>
198
+ inline Rational<Type> operator%(const Rational<OtherType>& other) const {
199
+ long floor_div = (this->n * other.n) / (this->d * other.d);
200
+ Rational<Type> prod = other * Rational<long>(floor_div, 1);
201
+
202
+ return Rational<long>(this->n, other.n) - prod;
203
+ }
204
+
205
+ template <typename OtherType>
206
+ inline bool operator<(const Rational<OtherType>& other) const {
207
+ return (this->n * other.d) < (other.n * this->d);
208
+ }
209
+
210
+ template <typename OtherType>
211
+ inline bool operator>(const Rational<OtherType>& other) const {
212
+ return (this->n * other.d) > (other.n * this->d);
213
+ }
214
+
215
+ template <typename OtherType>
216
+ inline bool operator==(const Rational<OtherType>& other) const {
217
+ return (this->n == other.n) && (this->d == other.d);
218
+ }
219
+
220
+ template <typename OtherType>
221
+ inline bool operator!=(const Rational<OtherType>& other) const {
222
+ return !(*this == other);
223
+ }
224
+
225
+ template <typename OtherType>
226
+ inline bool operator<=(const Rational<OtherType>& other) const {
227
+ return (*this < other) || (*this == other);
228
+ }
229
+
230
+ template <typename OtherType>
231
+ inline bool operator>=(const Rational<OtherType>& other) const {
232
+ return (*this > other) || (*this == other);
233
+ }
234
+
235
+ template <typename OtherType>
236
+ inline operator Rational<OtherType> () const {
237
+ return Rational<OtherType>((OtherType)this->n, (OtherType)this->d);
238
+ }
239
+
240
+ ////////////////////////////////
241
+ // Rational-Native Operations //
242
+ ////////////////////////////////
243
+
244
+ template <typename IntType, typename = typename std::enable_if<std::is_integral<IntType>::value>::type>
245
+ inline Rational<Type> operator+(const IntType& other) const {
246
+ return *this + Rational<Type>(other);
247
+ }
248
+
249
+ template <typename IntType, typename = typename std::enable_if<std::is_integral<IntType>::value>::type>
250
+ inline Rational<Type> operator-(const IntType& other) const {
251
+ return *this - Rational<Type>(other);
252
+ }
253
+
254
+ template <typename IntType, typename = typename std::enable_if<std::is_integral<IntType>::value>::type>
255
+ inline Rational<Type> operator*(const IntType& other) const {
256
+ return *this * Rational<Type>(other);
257
+ }
258
+
259
+ template <typename IntType, typename = typename std::enable_if<std::is_integral<IntType>::value>::type>
260
+ inline Rational<Type> operator/(const IntType& other) const {
261
+ return *this / Rational<Type>(other);
262
+ }
263
+
264
+ template <typename IntType, typename = typename std::enable_if<std::is_integral<IntType>::value>::type>
265
+ inline Rational<Type> operator%(const IntType& other) const {
266
+ return *this % Rational<Type>(other);
267
+ }
268
+
269
+ template <typename IntType, typename = typename std::enable_if<std::is_integral<IntType>::value>::type>
270
+ inline bool operator<(const IntType& other) const {
271
+ return *this < Rational<Type>(other);
272
+ }
273
+
274
+ template <typename IntType, typename = typename std::enable_if<std::is_integral<IntType>::value>::type>
275
+ inline bool operator>(const IntType& other) const {
276
+ return *this > Rational<Type>(other);
277
+ }
278
+
279
+ template <typename IntType, typename = typename std::enable_if<std::is_integral<IntType>::value>::type>
280
+ inline bool operator==(const IntType& other) const {
281
+ return *this == Rational<Type>(other);
282
+ }
283
+
284
+ template <typename IntType, typename = typename std::enable_if<std::is_integral<IntType>::value>::type>
285
+ inline bool operator!=(const IntType& other) const {
286
+ return *this != Rational<Type>(other);
287
+ }
288
+
289
+ template <typename IntType, typename = typename std::enable_if<std::is_integral<IntType>::value>::type>
290
+ inline bool operator<=(const IntType& other) const {
291
+ return *this <= Rational<Type>(other);
292
+ }
293
+
294
+ template <typename IntType, typename = typename std::enable_if<std::is_integral<IntType>::value>::type>
295
+ inline bool operator>=(const IntType& other) const {
296
+ return *this >= Rational<Type>(other);
297
+ }
298
+
299
+ template <typename NumType, typename = typename std::enable_if<std::is_arithmetic<NumType>::value>::type>
300
+ inline operator NumType () const {
301
+ return (NumType)this->n / (NumType)this->d;
302
+ }
303
+
304
+ /*
305
+ * Special casting operator for Complex numbers.
306
+ */
307
+ template <typename FloatType, typename = typename std::enable_if<std::is_floating_point<FloatType>::value>::type>
308
+ inline operator Rational<FloatType> () const {
309
+ return Rational<FloatType>(((FloatType)this->n) / ((FloatType)this->d));
310
+ }
307
311
  };
308
312
 
309
313
  // Negative operator
@@ -322,22 +326,22 @@ inline Rational<Type> operator-(const Rational<Type>& rhs) {
322
326
 
323
327
  template <typename IntType, typename RationalType, typename = typename std::enable_if<std::is_integral<IntType>::value>::type>
324
328
  inline Rational<RationalType> operator+(const IntType& left, const Rational<RationalType>& right) {
325
- return Rational<RationalType>(left) + right;
329
+ return Rational<RationalType>(left) + right;
326
330
  }
327
331
 
328
332
  template <typename IntType, typename RationalType, typename = typename std::enable_if<std::is_integral<IntType>::value>::type>
329
333
  inline Rational<RationalType> operator-(const IntType& left, const Rational<RationalType>& right) {
330
- return Rational<RationalType>(left) - right;
334
+ return Rational<RationalType>(left) - right;
331
335
  }
332
336
 
333
337
  template <typename IntType, typename RationalType, typename = typename std::enable_if<std::is_integral<IntType>::value>::type>
334
338
  inline Rational<RationalType> operator*(const IntType& left, const Rational<RationalType>& right) {
335
- return Rational<RationalType>(left) * right;
339
+ return Rational<RationalType>(left) * right;
336
340
  }
337
341
 
338
342
  template <typename IntType, typename RationalType, typename = typename std::enable_if<std::is_integral<IntType>::value>::type>
339
343
  inline Rational<RationalType> operator/(const IntType& left, const Rational<RationalType>& right) {
340
- return Rational<RationalType>(left) / right;
344
+ return Rational<RationalType>(left) / right;
341
345
  }
342
346
 
343
347
  /*
@@ -346,22 +350,22 @@ inline Rational<RationalType> operator/(const IntType& left, const Rational<Rati
346
350
 
347
351
  template <typename FloatType, typename RationalType, typename = typename std::enable_if<std::is_floating_point<FloatType>::value>::type>
348
352
  inline FloatType operator+(const FloatType& left, const Rational<RationalType>& right) {
349
- return left + (FloatType)right;
353
+ return left + (FloatType)right;
350
354
  }
351
355
 
352
356
  template <typename FloatType, typename RationalType, typename = typename std::enable_if<std::is_floating_point<FloatType>::value>::type>
353
357
  inline FloatType operator-(const FloatType& left, const Rational<RationalType>& right) {
354
- return left - (FloatType)right;
358
+ return left - (FloatType)right;
355
359
  }
356
360
 
357
361
  template <typename FloatType, typename RationalType, typename = typename std::enable_if<std::is_floating_point<FloatType>::value>::type>
358
362
  inline FloatType operator*(const FloatType& left, const Rational<RationalType>& right) {
359
- return left * (FloatType)right;
363
+ return left * (FloatType)right;
360
364
  }
361
365
 
362
366
  template <typename FloatType, typename RationalType, typename = typename std::enable_if<std::is_floating_point<FloatType>::value>::type>
363
367
  inline FloatType operator/(const FloatType& left, const Rational<RationalType>& right) {
364
- return left / (FloatType)right;
368
+ return left / (FloatType)right;
365
369
  }
366
370
 
367
371
  /*
@@ -370,44 +374,44 @@ inline FloatType operator/(const FloatType& left, const Rational<RationalType>&
370
374
 
371
375
  template <typename NativeType, typename RationalType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
372
376
  inline bool operator<(const NativeType left, const Rational<RationalType>& right) {
373
- //return Rational<RationalType>(left) < right;
374
- return (left * right.d) < right.n;
377
+ //return Rational<RationalType>(left) < right;
378
+ return (left * right.d) < right.n;
375
379
  }
376
380
 
377
381
  template <typename NativeType, typename RationalType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
378
382
  inline bool operator>(const NativeType left, const Rational<RationalType>& right) {
379
- //return Rational<RationalType>(left) > right;
380
- return (left * right.d) > right.n;
383
+ //return Rational<RationalType>(left) > right;
384
+ return (left * right.d) > right.n;
381
385
  }
382
386
 
383
387
  template <typename IntType, typename RationalType>
384
388
  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;
389
+ //return Rational<RationalType>(left) == right;
390
+ return (left * right.d) == right.n;
387
391
  }
388
392
 
389
393
  template <typename FloatType, typename RationalType>
390
394
  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));
395
+ //return Rational<RationalType>(left) == right;
396
+ return FP_EQUAL(left, ((FloatType)right));
393
397
  }
394
398
 
395
399
  template <typename NativeType, typename RationalType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
396
400
  inline bool operator!=(const NativeType left, const Rational<RationalType>& right) {
397
- //return Rational<RationalType>(left) != right;
398
- return !(left == right);
401
+ //return Rational<RationalType>(left) != right;
402
+ return !(left == right);
399
403
  }
400
404
 
401
405
  template <typename NativeType, typename RationalType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
402
406
  inline bool operator<=(const NativeType left, const Rational<RationalType>& right) {
403
- //return Rational<RationalType>(left) <= right;
404
- return (left < right) or (left == right);
407
+ //return Rational<RationalType>(left) <= right;
408
+ return (left < right) or (left == right);
405
409
  }
406
410
 
407
411
  template <typename NativeType, typename RationalType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
408
412
  inline bool operator>=(const NativeType left, const Rational<RationalType>& right) {
409
- //return Rational<RationalType>(left) >= right;
410
- return (left > right) or (left == right);
413
+ //return Rational<RationalType>(left) >= right;
414
+ return (left > right) or (left == right);
411
415
  }
412
416
 
413
417
  template <typename Type>