nmatrix 0.0.1 → 0.0.2
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/.gitignore +27 -0
- data/.rspec +2 -0
- data/Gemfile +3 -5
- data/Guardfile +6 -0
- data/History.txt +33 -0
- data/Manifest.txt +41 -38
- data/README.rdoc +88 -11
- data/Rakefile +35 -53
- data/ext/nmatrix/data/complex.h +372 -0
- data/ext/nmatrix/data/data.cpp +275 -0
- data/ext/nmatrix/data/data.h +707 -0
- data/ext/nmatrix/data/rational.h +421 -0
- data/ext/nmatrix/data/ruby_object.h +446 -0
- data/ext/nmatrix/extconf.rb +101 -51
- data/ext/nmatrix/new_extconf.rb +56 -0
- data/ext/nmatrix/nmatrix.cpp +1609 -0
- data/ext/nmatrix/nmatrix.h +265 -849
- data/ext/nmatrix/ruby_constants.cpp +134 -0
- data/ext/nmatrix/ruby_constants.h +103 -0
- data/ext/nmatrix/storage/common.cpp +70 -0
- data/ext/nmatrix/storage/common.h +170 -0
- data/ext/nmatrix/storage/dense.cpp +665 -0
- data/ext/nmatrix/storage/dense.h +116 -0
- data/ext/nmatrix/storage/list.cpp +1088 -0
- data/ext/nmatrix/storage/list.h +129 -0
- data/ext/nmatrix/storage/storage.cpp +658 -0
- data/ext/nmatrix/storage/storage.h +99 -0
- data/ext/nmatrix/storage/yale.cpp +1601 -0
- data/ext/nmatrix/storage/yale.h +208 -0
- data/ext/nmatrix/ttable_helper.rb +126 -0
- data/ext/nmatrix/{yale/smmp1_header.template.c → types.h} +36 -9
- data/ext/nmatrix/util/io.cpp +295 -0
- data/ext/nmatrix/util/io.h +117 -0
- data/ext/nmatrix/util/lapack.h +1175 -0
- data/ext/nmatrix/util/math.cpp +557 -0
- data/ext/nmatrix/util/math.h +1363 -0
- data/ext/nmatrix/util/sl_list.cpp +475 -0
- data/ext/nmatrix/util/sl_list.h +255 -0
- data/ext/nmatrix/util/util.h +78 -0
- data/lib/nmatrix/blas.rb +70 -0
- data/lib/nmatrix/io/mat5_reader.rb +567 -0
- data/lib/nmatrix/io/mat_reader.rb +162 -0
- data/lib/{string.rb → nmatrix/monkeys.rb} +49 -2
- data/lib/nmatrix/nmatrix.rb +199 -0
- data/lib/nmatrix/nvector.rb +103 -0
- data/lib/nmatrix/version.rb +27 -0
- data/lib/nmatrix.rb +22 -230
- data/nmatrix.gemspec +59 -0
- data/scripts/mac-brew-gcc.sh +47 -0
- data/spec/4x4_sparse.mat +0 -0
- data/spec/4x5_dense.mat +0 -0
- data/spec/blas_spec.rb +47 -0
- data/spec/elementwise_spec.rb +164 -0
- data/spec/io_spec.rb +60 -0
- data/spec/lapack_spec.rb +52 -0
- data/spec/math_spec.rb +96 -0
- data/spec/nmatrix_spec.rb +93 -89
- data/spec/nmatrix_yale_spec.rb +52 -36
- data/spec/nvector_spec.rb +1 -1
- data/spec/slice_spec.rb +257 -0
- data/spec/spec_helper.rb +51 -0
- data/spec/utm5940.mtx +83844 -0
- metadata +113 -71
- data/.autotest +0 -23
- data/.gemtest +0 -0
- data/ext/nmatrix/cblas.c +0 -150
- data/ext/nmatrix/dense/blas_header.template.c +0 -52
- data/ext/nmatrix/dense/elementwise.template.c +0 -107
- data/ext/nmatrix/dense/gemm.template.c +0 -159
- data/ext/nmatrix/dense/gemv.template.c +0 -130
- data/ext/nmatrix/dense/rationalmath.template.c +0 -68
- data/ext/nmatrix/dense.c +0 -307
- data/ext/nmatrix/depend +0 -18
- data/ext/nmatrix/generator/syntax_tree.rb +0 -481
- data/ext/nmatrix/generator.rb +0 -594
- data/ext/nmatrix/list.c +0 -774
- data/ext/nmatrix/nmatrix.c +0 -1977
- data/ext/nmatrix/rational.c +0 -98
- data/ext/nmatrix/yale/complexmath.template.c +0 -71
- data/ext/nmatrix/yale/elementwise.template.c +0 -46
- data/ext/nmatrix/yale/elementwise_op.template.c +0 -73
- data/ext/nmatrix/yale/numbmm.template.c +0 -94
- data/ext/nmatrix/yale/smmp1.template.c +0 -21
- data/ext/nmatrix/yale/smmp2.template.c +0 -43
- data/ext/nmatrix/yale/smmp2_header.template.c +0 -46
- data/ext/nmatrix/yale/sort_columns.template.c +0 -56
- data/ext/nmatrix/yale/symbmm.template.c +0 -54
- data/ext/nmatrix/yale/transp.template.c +0 -68
- data/ext/nmatrix/yale.c +0 -726
- data/lib/array.rb +0 -67
- data/spec/syntax_tree_spec.rb +0 -46
|
@@ -0,0 +1,446 @@
|
|
|
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 - 2012, Ruby Science Foundation
|
|
13
|
+
// NMatrix is Copyright (c) 2012, 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
|
+
// == ruby_object.h
|
|
25
|
+
//
|
|
26
|
+
// Functions and classes for dealing with Ruby objects.
|
|
27
|
+
|
|
28
|
+
#ifndef RUBY_OBJECT_H
|
|
29
|
+
#define RUBY_OBJECT_H
|
|
30
|
+
|
|
31
|
+
/*
|
|
32
|
+
* Standard Includes
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
#include <ruby.h>
|
|
36
|
+
#include <iostream>
|
|
37
|
+
#include <type_traits>
|
|
38
|
+
|
|
39
|
+
/*
|
|
40
|
+
* Project Includes
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
#include "ruby_constants.h"
|
|
44
|
+
|
|
45
|
+
/*
|
|
46
|
+
* Macros
|
|
47
|
+
*/
|
|
48
|
+
#define NM_RUBYVAL_IS_NUMERIC(val) (FIXNUM_P(val) or (TYPE(val) == T_FLOAT) or (TYPE(val) == T_COMPLEX) or (TYPE(val) == T_RATIONAL))
|
|
49
|
+
#define NMATRIX_CHECK_TYPE(val) \
|
|
50
|
+
if (TYPE(val) != T_DATA || (RDATA(val)->dfree != (RUBY_DATA_FUNC)nm_delete && RDATA(val)->dfree != (RUBY_DATA_FUNC)nm_delete_ref)) \
|
|
51
|
+
rb_raise(rb_eTypeError, "Expected NMatrix on left-hand side of operation.");
|
|
52
|
+
|
|
53
|
+
/*
|
|
54
|
+
* Types
|
|
55
|
+
*/
|
|
56
|
+
|
|
57
|
+
/*
|
|
58
|
+
* Data
|
|
59
|
+
*/
|
|
60
|
+
|
|
61
|
+
/*
|
|
62
|
+
* Classes and Functions
|
|
63
|
+
*/
|
|
64
|
+
namespace nm {
|
|
65
|
+
template<typename T, typename U>
|
|
66
|
+
struct made_from_same_template : std::false_type {};
|
|
67
|
+
|
|
68
|
+
template<template<typename> class Templ, typename Arg1, typename Arg2>
|
|
69
|
+
struct made_from_same_template<Templ<Arg1>, Templ<Arg2>> : std::true_type {};
|
|
70
|
+
|
|
71
|
+
class RubyObject {
|
|
72
|
+
public:
|
|
73
|
+
VALUE rval;
|
|
74
|
+
|
|
75
|
+
/*
|
|
76
|
+
* Value constructor.
|
|
77
|
+
*/
|
|
78
|
+
inline RubyObject(VALUE ref = Qnil) : rval(ref) {}
|
|
79
|
+
|
|
80
|
+
/*
|
|
81
|
+
* Complex number constructor.
|
|
82
|
+
*/
|
|
83
|
+
template <typename FloatType, typename = typename std::enable_if<std::is_floating_point<FloatType>::value>::type>
|
|
84
|
+
inline RubyObject(const Complex<FloatType>& other) : rval(rb_complex_new(rb_float_new(other.r), rb_float_new(other.i))) {}
|
|
85
|
+
|
|
86
|
+
/*
|
|
87
|
+
* Rational number constructor.
|
|
88
|
+
*/
|
|
89
|
+
template <typename IntType, typename = typename std::enable_if<std::is_integral<IntType>::value>::type>
|
|
90
|
+
inline RubyObject(const Rational<IntType>& other) : rval(rb_rational_new(INT2FIX(other.n), INT2FIX(other.d))) {}
|
|
91
|
+
|
|
92
|
+
/*
|
|
93
|
+
* Integer constructor.
|
|
94
|
+
*
|
|
95
|
+
* Does not work as a template.
|
|
96
|
+
*/
|
|
97
|
+
inline RubyObject(uint8_t other) : rval(INT2FIX(other)) {}
|
|
98
|
+
inline RubyObject(int8_t other) : rval(INT2FIX(other)) {}
|
|
99
|
+
inline RubyObject(int16_t other) : rval(INT2FIX(other)) {}
|
|
100
|
+
inline RubyObject(uint16_t other) : rval(INT2FIX(other)) {}
|
|
101
|
+
inline RubyObject(int32_t other) : rval(INT2FIX(other)) {}
|
|
102
|
+
// there is no uint32_t here because that's a Ruby VALUE type, and we need the compiler to treat that as a VALUE.
|
|
103
|
+
inline RubyObject(int64_t other) : rval(INT2FIX(other)) {}
|
|
104
|
+
// inline RubyObject(uint64_t other) : rval(INT2FIX(other)) {}
|
|
105
|
+
|
|
106
|
+
/*
|
|
107
|
+
* Float constructor.
|
|
108
|
+
*
|
|
109
|
+
* Does not work as a template.
|
|
110
|
+
*/
|
|
111
|
+
inline RubyObject(float other) : rval(rb_float_new(other)) {}
|
|
112
|
+
inline RubyObject(double other) : rval(rb_float_new(other)) {}
|
|
113
|
+
|
|
114
|
+
/*
|
|
115
|
+
* Copy constructors.
|
|
116
|
+
*/
|
|
117
|
+
inline RubyObject(const RubyObject& other) : rval(other.rval) {}
|
|
118
|
+
|
|
119
|
+
/*
|
|
120
|
+
* Inverse operator.
|
|
121
|
+
*/
|
|
122
|
+
inline RubyObject inverse() const {
|
|
123
|
+
rb_raise(rb_eNotImpError, "RubyObject#inverse needs to be implemented");
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/*
|
|
127
|
+
* Absolute value.
|
|
128
|
+
*/
|
|
129
|
+
inline RubyObject abs() const {
|
|
130
|
+
return RubyObject(rb_funcall(this->rval, rb_intern("abs"), 0));
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/*
|
|
134
|
+
* Binary operator definitions.
|
|
135
|
+
*/
|
|
136
|
+
|
|
137
|
+
inline RubyObject operator+(const RubyObject& other) const {
|
|
138
|
+
return RubyObject(rb_funcall(this->rval, nm_rb_add, 1, other.rval));
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
inline RubyObject& operator+=(const RubyObject& other) {
|
|
142
|
+
this->rval = rb_funcall(this->rval, nm_rb_add, 1, other.rval);
|
|
143
|
+
return *this;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
inline RubyObject operator-(const RubyObject& other) const {
|
|
147
|
+
return RubyObject(rb_funcall(this->rval, nm_rb_sub, 1, other.rval));
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
inline RubyObject& operator-=(const RubyObject& other) {
|
|
151
|
+
this->rval = rb_funcall(this->rval, nm_rb_sub, 1, other.rval);
|
|
152
|
+
return *this;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
inline RubyObject operator*(const RubyObject& other) const {
|
|
156
|
+
return RubyObject(rb_funcall(this->rval, nm_rb_mul, 1, other.rval));
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
inline RubyObject& operator*=(const RubyObject& other) {
|
|
160
|
+
this->rval = rb_funcall(this->rval, nm_rb_mul, 1, other.rval);
|
|
161
|
+
return *this;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
inline RubyObject operator/(const RubyObject& other) const {
|
|
165
|
+
return RubyObject(rb_funcall(this->rval, nm_rb_div, 1, other.rval));
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
inline RubyObject& operator/=(const RubyObject& other) {
|
|
169
|
+
this->rval = rb_funcall(this->rval, nm_rb_div, 1, other.rval);
|
|
170
|
+
return *this;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
inline RubyObject operator%(const RubyObject& other) const {
|
|
174
|
+
return RubyObject(rb_funcall(this->rval, nm_rb_percent, 1, other.rval));
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
inline bool operator>(const RubyObject& other) const {
|
|
178
|
+
return rb_funcall(this->rval, nm_rb_gt, 1, other.rval) == Qtrue;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
inline bool operator<(const RubyObject& other) const {
|
|
182
|
+
return rb_funcall(this->rval, nm_rb_lt, 1, other.rval) == Qtrue;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
template <typename OtherType>
|
|
186
|
+
inline bool operator<(const OtherType& other) const {
|
|
187
|
+
return *this < RubyObject(other);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
inline bool operator==(const RubyObject& other) const {
|
|
191
|
+
return rb_funcall(this->rval, nm_rb_eql, 1, other.rval) == Qtrue;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
template <typename OtherType>
|
|
195
|
+
inline bool operator==(const OtherType& other) const {
|
|
196
|
+
return *this == RubyObject(other);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
inline bool operator!=(const RubyObject& other) const {
|
|
200
|
+
return rb_funcall(this->rval, nm_rb_neql, 1, other.rval) == Qtrue;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
template <typename OtherType>
|
|
204
|
+
inline bool operator!=(const OtherType& other) const {
|
|
205
|
+
return *this != RubyObject(other);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
inline bool operator>=(const RubyObject& other) const {
|
|
209
|
+
return rb_funcall(this->rval, nm_rb_gte, 1, other.rval) == Qtrue;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
template <typename OtherType>
|
|
213
|
+
inline bool operator>=(const OtherType& other) const {
|
|
214
|
+
return *this >= RubyObject(other);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
inline bool operator<=(const RubyObject& other) const {
|
|
218
|
+
return rb_funcall(this->rval, nm_rb_lte, 1, other.rval) == Qtrue;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
template <typename OtherType>
|
|
222
|
+
inline bool operator<=(const OtherType& other) const {
|
|
223
|
+
return *this <= RubyObject(other);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
////////////////////////////
|
|
227
|
+
// RUBY-NATIVE OPERATIONS //
|
|
228
|
+
////////////////////////////
|
|
229
|
+
/*
|
|
230
|
+
template <typename NativeType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
|
|
231
|
+
inline bool operator==(const NativeType& other) const {
|
|
232
|
+
return *this == RubyObject(other);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
template <typename NativeType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
|
|
236
|
+
inline bool operator!=(const NativeType& other) const {
|
|
237
|
+
return *this != RubyObject(other);
|
|
238
|
+
}
|
|
239
|
+
*/
|
|
240
|
+
//////////////////////////////
|
|
241
|
+
// RUBY-RATIONAL OPERATIONS //
|
|
242
|
+
//////////////////////////////
|
|
243
|
+
|
|
244
|
+
template <typename IntType, typename = typename std::enable_if<std::is_integral<IntType>::value>::type>
|
|
245
|
+
inline bool operator==(const Rational<IntType>& other) const {
|
|
246
|
+
return *this == RubyObject(other);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
template <typename IntType, typename = typename std::enable_if<std::is_integral<IntType>::value>::type>
|
|
250
|
+
inline bool operator!=(const Rational<IntType>& other) const {
|
|
251
|
+
return *this != RubyObject(other);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
//////////////////////////////
|
|
255
|
+
// RUBY-COMPLEX OPERATIONS //
|
|
256
|
+
//////////////////////////////
|
|
257
|
+
|
|
258
|
+
template <typename FloatType, typename = typename std::enable_if<std::is_floating_point<FloatType>::value>::type>
|
|
259
|
+
inline bool operator==(const Complex<FloatType>& other) const {
|
|
260
|
+
return *this == RubyObject(other);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
template <typename FloatType, typename = typename std::enable_if<std::is_floating_point<FloatType>::value>::type>
|
|
264
|
+
inline bool operator!=(const Complex<FloatType>& other) const {
|
|
265
|
+
return *this != RubyObject(other);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/*
|
|
269
|
+
* Convert a Ruby object to an integer.
|
|
270
|
+
*/
|
|
271
|
+
template <typename IntType>
|
|
272
|
+
inline typename std::enable_if<std::is_integral<IntType>::value, IntType>::type to(void) {
|
|
273
|
+
return NUM2INT(this->rval);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/*
|
|
277
|
+
* Convert a Ruby object to a floating point number.
|
|
278
|
+
*/
|
|
279
|
+
template <typename FloatType>
|
|
280
|
+
inline typename std::enable_if<std::is_floating_point<FloatType>::value, FloatType>::type to(void) {
|
|
281
|
+
return NUM2DBL(this->rval);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/*
|
|
285
|
+
* Convert a Ruby object to a complex number.
|
|
286
|
+
*/
|
|
287
|
+
template <typename ComplexType>
|
|
288
|
+
inline typename std::enable_if<made_from_same_template<ComplexType, Complex64>::value, ComplexType>::type to(void) {
|
|
289
|
+
if (FIXNUM_P(this->rval) or TYPE(this->rval) == T_FLOAT or TYPE(this->rval) == T_RATIONAL) {
|
|
290
|
+
return ComplexType(NUM2DBL(this->rval));
|
|
291
|
+
|
|
292
|
+
} else if (TYPE(this->rval) == T_COMPLEX) {
|
|
293
|
+
return ComplexType(NUM2DBL(rb_funcall(this->rval, nm_rb_real, 0)), NUM2DBL(rb_funcall(this->rval, nm_rb_imag, 0)));
|
|
294
|
+
|
|
295
|
+
} else {
|
|
296
|
+
rb_raise(rb_eTypeError, "Invalid conversion to Complex type.");
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/*
|
|
301
|
+
* Convert a Ruby object to a rational number.
|
|
302
|
+
*/
|
|
303
|
+
template <typename RationalType>
|
|
304
|
+
inline typename std::enable_if<made_from_same_template<RationalType, Rational32>::value, RationalType>::type to(void) {
|
|
305
|
+
if (FIXNUM_P(this->rval) or TYPE(this->rval) == T_FLOAT or TYPE(this->rval) == T_COMPLEX) {
|
|
306
|
+
return RationalType(NUM2INT(this->rval));
|
|
307
|
+
|
|
308
|
+
} else if (TYPE(this->rval) == T_RATIONAL) {
|
|
309
|
+
return RationalType(NUM2INT(rb_funcall(this->rval, nm_rb_numer, 0)), NUM2INT(rb_funcall(this->rval, nm_rb_denom, 0)));
|
|
310
|
+
|
|
311
|
+
} else {
|
|
312
|
+
rb_raise(rb_eTypeError, "Invalid conversion to Rational type.");
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
template <typename OtherType>
|
|
317
|
+
inline operator OtherType () {
|
|
318
|
+
return to<OtherType>();
|
|
319
|
+
}
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
////////////////////////////
|
|
324
|
+
// NATIVE-RUBY OPERATIONS //
|
|
325
|
+
////////////////////////////
|
|
326
|
+
|
|
327
|
+
template <typename NativeType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
|
|
328
|
+
inline RubyObject operator/(const NativeType left, const RubyObject& right) {
|
|
329
|
+
return RubyObject(left) / right;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
template <typename NativeType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
|
|
333
|
+
inline bool operator==(const NativeType left, const RubyObject& right) {
|
|
334
|
+
return RubyObject(left) == right;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
template <typename NativeType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
|
|
338
|
+
inline bool operator!=(const NativeType left, const RubyObject& right) {
|
|
339
|
+
return RubyObject(left) != right;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
template <typename NativeType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
|
|
343
|
+
inline bool operator<=(const NativeType left, const RubyObject& right) {
|
|
344
|
+
return RubyObject(left) <= right;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
template <typename NativeType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
|
|
348
|
+
inline bool operator>=(const NativeType left, const RubyObject& right) {
|
|
349
|
+
return RubyObject(left) >= right;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
template <typename NativeType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
|
|
353
|
+
inline bool operator<(const NativeType left, const RubyObject& right) {
|
|
354
|
+
return RubyObject(left) < right;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
template <typename NativeType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
|
|
358
|
+
inline bool operator>(const NativeType left, const RubyObject& right) {
|
|
359
|
+
return RubyObject(left) > right;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
/////////////////////////////
|
|
364
|
+
// COMPLEX-RUBY OPERATIONS //
|
|
365
|
+
/////////////////////////////
|
|
366
|
+
|
|
367
|
+
template <typename FloatType, typename = typename std::enable_if<std::is_floating_point<FloatType>::value>::type>
|
|
368
|
+
inline bool operator==(const Complex<FloatType>& left, const RubyObject& right) {
|
|
369
|
+
return RubyObject(left) == right;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
template <typename FloatType, typename = typename std::enable_if<std::is_floating_point<FloatType>::value>::type>
|
|
373
|
+
inline bool operator!=(const Complex<FloatType>& left, const RubyObject& right) {
|
|
374
|
+
return RubyObject(left) != right;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
template <typename FloatType, typename = typename std::enable_if<std::is_floating_point<FloatType>::value>::type>
|
|
378
|
+
inline bool operator<=(const Complex<FloatType>& left, const RubyObject& right) {
|
|
379
|
+
return RubyObject(left) <= right;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
template <typename FloatType, typename = typename std::enable_if<std::is_floating_point<FloatType>::value>::type>
|
|
383
|
+
inline bool operator>=(const Complex<FloatType>& left, const RubyObject& right) {
|
|
384
|
+
return RubyObject(left) >= right;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
template <typename FloatType, typename = typename std::enable_if<std::is_floating_point<FloatType>::value>::type>
|
|
388
|
+
inline bool operator<(const Complex<FloatType>& left, const RubyObject& right) {
|
|
389
|
+
return RubyObject(left) < right;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
template <typename FloatType, typename = typename std::enable_if<std::is_floating_point<FloatType>::value>::type>
|
|
393
|
+
inline bool operator>(const Complex<FloatType>& left, const RubyObject& right) {
|
|
394
|
+
return RubyObject(left) > right;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
//////////////////////////////
|
|
400
|
+
// RATIONAL-RUBY OPERATIONS //
|
|
401
|
+
//////////////////////////////
|
|
402
|
+
|
|
403
|
+
template <typename IntType, typename = typename std::enable_if<std::is_integral<IntType>::value>::type>
|
|
404
|
+
inline bool operator==(const Rational<IntType>& left, const RubyObject& right) {
|
|
405
|
+
return RubyObject(left) == right;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
template <typename IntType, typename = typename std::enable_if<std::is_integral<IntType>::value>::type>
|
|
409
|
+
inline bool operator!=(const Rational<IntType>& left, const RubyObject& right) {
|
|
410
|
+
return RubyObject(left) != right;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
template <typename IntType, typename = typename std::enable_if<std::is_integral<IntType>::value>::type>
|
|
414
|
+
inline bool operator>=(const Rational<IntType>& left, const RubyObject& right) {
|
|
415
|
+
return RubyObject(left) >= right;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
template <typename IntType, typename = typename std::enable_if<std::is_integral<IntType>::value>::type>
|
|
419
|
+
inline bool operator<=(const Rational<IntType>& left, const RubyObject& right) {
|
|
420
|
+
return RubyObject(left) <= right;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
template <typename IntType, typename = typename std::enable_if<std::is_integral<IntType>::value>::type>
|
|
424
|
+
inline bool operator<(const Rational<IntType>& left, const RubyObject& right) {
|
|
425
|
+
return RubyObject(left) < right;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
template <typename IntType, typename = typename std::enable_if<std::is_integral<IntType>::value>::type>
|
|
429
|
+
inline bool operator>(const Rational<IntType>& left, const RubyObject& right) {
|
|
430
|
+
return RubyObject(left) > right;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
inline std::ostream& operator<<(std::ostream& out, const RubyObject& rhs) {
|
|
434
|
+
out << "RUBYOBJECT" << std::flush; // FIXME: Try calling inspect or something on the Ruby object if we really need to debug it.
|
|
435
|
+
return out;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
} // end of namespace nm
|
|
439
|
+
|
|
440
|
+
namespace std {
|
|
441
|
+
inline nm::RubyObject abs(const nm::RubyObject& obj) {
|
|
442
|
+
return obj.abs();
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
#endif // RUBY_OBJECT_H
|
data/ext/nmatrix/extconf.rb
CHANGED
|
@@ -22,11 +22,13 @@
|
|
|
22
22
|
#
|
|
23
23
|
# == extconf.rb
|
|
24
24
|
#
|
|
25
|
-
# This file
|
|
25
|
+
# This file checks for ATLAS and other necessary headers, and
|
|
26
|
+
# generates a Makefile for compiling NMatrix.
|
|
26
27
|
|
|
27
28
|
require "mkmf"
|
|
28
29
|
|
|
29
30
|
|
|
31
|
+
# Function derived from NArray's extconf.rb.
|
|
30
32
|
def have_type(type, header=nil)
|
|
31
33
|
printf "checking for %s... ", type
|
|
32
34
|
STDOUT.flush
|
|
@@ -57,20 +59,30 @@ SRC
|
|
|
57
59
|
return true
|
|
58
60
|
end
|
|
59
61
|
|
|
62
|
+
# Function derived from NArray's extconf.rb.
|
|
60
63
|
def create_conf_h(file)
|
|
61
64
|
print "creating #{file}\n"
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
65
|
+
File.open(file, 'w') do |hfile|
|
|
66
|
+
header_guard = file.upcase.sub(/\s|\./, '_')
|
|
67
|
+
|
|
68
|
+
hfile.puts "#ifndef #{header_guard}"
|
|
69
|
+
hfile.puts "#define #{header_guard}"
|
|
70
|
+
hfile.puts
|
|
71
|
+
|
|
72
|
+
for line in $defs
|
|
73
|
+
line =~ /^-D(.*)/
|
|
74
|
+
hfile.printf "#define %s 1\n", $1
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
hfile.puts
|
|
78
|
+
hfile.puts "#endif"
|
|
66
79
|
end
|
|
67
|
-
hfile.close
|
|
68
80
|
end
|
|
69
81
|
|
|
70
82
|
if RUBY_VERSION < '1.9'
|
|
71
83
|
raise(NotImplementedError, "Sorry, you need Ruby 1.9!")
|
|
72
84
|
else
|
|
73
|
-
$INSTALLFILES = [['nmatrix.h', '$(archdir)'], ['nmatrix_config.h', '$(archdir)']]
|
|
85
|
+
$INSTALLFILES = [['nmatrix.h', '$(archdir)'], ['nmatrix.hpp', '$(archdir)'], ['nmatrix_config.h', '$(archdir)']]
|
|
74
86
|
if /cygwin|mingw/ =~ RUBY_PLATFORM
|
|
75
87
|
$INSTALLFILES << ['libnmatrix.a', '$(archdir)']
|
|
76
88
|
end
|
|
@@ -81,63 +93,101 @@ if /cygwin|mingw/ =~ RUBY_PLATFORM
|
|
|
81
93
|
end
|
|
82
94
|
|
|
83
95
|
$DEBUG = true
|
|
84
|
-
$CFLAGS = ["-Wall ",$CFLAGS].join(" ")
|
|
85
|
-
|
|
86
|
-
srcs =
|
|
87
|
-
nmatrix
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
96
|
+
$CFLAGS = ["-Wall ",$CFLAGS].join(" ")
|
|
97
|
+
|
|
98
|
+
$srcs = [
|
|
99
|
+
'nmatrix.cpp',
|
|
100
|
+
'ruby_constants.cpp',
|
|
101
|
+
|
|
102
|
+
'data/data.cpp',
|
|
103
|
+
'util/math.cpp',
|
|
104
|
+
'util/sl_list.cpp',
|
|
105
|
+
'util/io.cpp',
|
|
106
|
+
'storage/common.cpp',
|
|
107
|
+
'storage/storage.cpp',
|
|
108
|
+
'storage/dense.cpp',
|
|
109
|
+
'storage/yale.cpp',
|
|
110
|
+
'storage/list.cpp'
|
|
111
|
+
]
|
|
98
112
|
# add smmp in to get generic transp; remove smmp2 to eliminate funcptr transp
|
|
99
113
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
unless have_header(header)
|
|
104
|
-
header = nil
|
|
105
|
-
end
|
|
106
|
-
end
|
|
114
|
+
# The next line allows the user to supply --with-atlas-include=/usr/local/atlas, for example,
|
|
115
|
+
# and tell the compiler where to look for ATLAS.
|
|
116
|
+
dir_config("atlas")
|
|
107
117
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
have_type("int32_t", header)
|
|
114
|
-
have_type("u_int32_t", header)
|
|
115
|
-
have_type("uint32_t", header)
|
|
116
|
-
have_type("int64_t", header)
|
|
117
|
-
have_type("u_int64_t", header)
|
|
118
|
-
have_type("uint64_t", header)
|
|
119
|
-
|
|
120
|
-
unless have_type("size_t", header)
|
|
121
|
-
have_type("size_t", "stddef.h")
|
|
122
|
-
end
|
|
118
|
+
# Is g++ having trouble finding your header files?
|
|
119
|
+
# Try this:
|
|
120
|
+
# export C_INCLUDE_PATH=/usr/local/atlas/include
|
|
121
|
+
# export CPLUS_INCLUDE_PATH=/usr/local/atlas/include
|
|
122
|
+
# (substituting in the path of your cblas.h and clapack.h for the path I used). -- JW 8/27/12
|
|
123
123
|
|
|
124
|
-
|
|
125
|
-
|
|
124
|
+
find_library("lapack", "clapack_dgetrf", "/usr/local/lib", "/usr/local/atlas/lib")
|
|
125
|
+
have_header("clapack.h")
|
|
126
126
|
|
|
127
127
|
find_library("cblas", "cblas_dgemm", "/usr/local/lib", "/usr/local/atlas/lib")
|
|
128
128
|
find_library("atlas", "ATL_dgemmNN", "/usr/local/lib", "/usr/local/atlas/lib", "/usr/lib")
|
|
129
|
-
|
|
129
|
+
have_header("cblas.h")
|
|
130
130
|
|
|
131
|
-
|
|
132
|
-
|
|
131
|
+
# Order matters here: ATLAS has to go after LAPACK: http://mail.scipy.org/pipermail/scipy-user/2007-January/010717.html
|
|
132
|
+
$libs += " -llapack -lcblas -latlas "
|
|
133
133
|
|
|
134
|
+
$objs = %w{nmatrix ruby_constants data/data util/io util/math util/sl_list storage/common storage/storage storage/dense storage/yale storage/list}.map { |i| i + ".o" }
|
|
134
135
|
|
|
135
|
-
|
|
136
|
+
#CONFIG['CXX'] = 'clang++'
|
|
137
|
+
CONFIG['CXX'] = 'g++'
|
|
136
138
|
|
|
137
|
-
|
|
139
|
+
def find_newer_gplusplus
|
|
140
|
+
[7,6,5,4,3].each do |minor|
|
|
141
|
+
result = `which g++-4.#{minor}`
|
|
142
|
+
next if result.empty?
|
|
143
|
+
CONFIG['CXX'] = "g++-4.#{minor}"
|
|
144
|
+
return CONFIG['CXX']
|
|
145
|
+
end
|
|
146
|
+
false
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def gplusplus_version
|
|
150
|
+
`#{CONFIG['CXX']} -v 2>&1`.lines.to_a.last.match(/gcc\sversion\s(\d\.\d.\d)/).captures.first
|
|
151
|
+
end
|
|
138
152
|
|
|
139
|
-
|
|
153
|
+
|
|
154
|
+
if CONFIG['CXX'] == 'clang++'
|
|
155
|
+
$CPP_STANDARD = 'c++11'
|
|
156
|
+
|
|
157
|
+
else
|
|
158
|
+
version = gplusplus_version
|
|
159
|
+
if version < '4.3.0' && CONFIG['CXX'] == 'g++' # see if we can find a newer G++, unless it's been overridden by user
|
|
160
|
+
if !find_newer_gplusplus
|
|
161
|
+
raise("You need a version of g++ which supports -std=c++0x or -std=c++11. If you're on a Mac and using Homebrew, we recommend using mac-brew-gcc.sh to install a more recent g++.")
|
|
162
|
+
end
|
|
163
|
+
version = gplusplus_version
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
if version < '4.7.0'
|
|
167
|
+
$CPP_STANDARD = 'c++0x'
|
|
168
|
+
else
|
|
169
|
+
$CPP_STANDARD = 'c++11'
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
# For release, these next two should both be changed to -O3.
|
|
174
|
+
$CFLAGS += " -O0 "
|
|
175
|
+
$CPPFLAGS += " -O0 -std=#{$CPP_STANDARD} " #-fmax-errors=10 -save-temps
|
|
176
|
+
|
|
177
|
+
CONFIG['warnflags'].gsub!('-Wshorten-64-to-32', '') # doesn't work except in Mac-patched gcc (4.2)
|
|
178
|
+
CONFIG['warnflags'].gsub!('-Wdeclaration-after-statement', '')
|
|
179
|
+
CONFIG['warnflags'].gsub!('-Wimplicit-function-declaration', '')
|
|
140
180
|
|
|
141
181
|
create_conf_h("nmatrix_config.h")
|
|
142
182
|
create_makefile("nmatrix")
|
|
143
183
|
|
|
184
|
+
Dir.mkdir("data") unless Dir.exists?("data")
|
|
185
|
+
Dir.mkdir("util") unless Dir.exists?("util")
|
|
186
|
+
Dir.mkdir("storage") unless Dir.exists?("storage")
|
|
187
|
+
|
|
188
|
+
# to clean up object files in subdirectories:
|
|
189
|
+
open('Makefile', 'a') do |f|
|
|
190
|
+
f.write <<EOS
|
|
191
|
+
CLEANOBJS := $(CLEANOBJS) data/*.#{CONFIG["OBJEXT"]} storage/*.#{CONFIG["OBJEXT"]} util/*.#{CONFIG["OBJEXT"]}
|
|
192
|
+
EOS
|
|
193
|
+
end
|