nmatrix 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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,372 @@
|
|
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
|
+
// == complex.h
|
25
|
+
//
|
26
|
+
// Functions and classes for dealing with complex numbers.
|
27
|
+
|
28
|
+
#ifndef COMPLEX_H
|
29
|
+
#define COMPLEX_H
|
30
|
+
|
31
|
+
/*
|
32
|
+
* Standard Includes
|
33
|
+
*/
|
34
|
+
|
35
|
+
#include <type_traits>
|
36
|
+
#include <iostream>
|
37
|
+
|
38
|
+
/*
|
39
|
+
* Project Includes
|
40
|
+
*/
|
41
|
+
|
42
|
+
#include "types.h"
|
43
|
+
|
44
|
+
/*
|
45
|
+
* Macros
|
46
|
+
*/
|
47
|
+
|
48
|
+
/*
|
49
|
+
* Types
|
50
|
+
*/
|
51
|
+
namespace nm {
|
52
|
+
|
53
|
+
template <typename IntType> class Rational;
|
54
|
+
template <typename Type> class Complex;
|
55
|
+
|
56
|
+
typedef Complex<float32_t> Complex64;
|
57
|
+
typedef Complex<float64_t> Complex128;
|
58
|
+
|
59
|
+
/*
|
60
|
+
* Data
|
61
|
+
*/
|
62
|
+
|
63
|
+
/*
|
64
|
+
* Classes and Functions
|
65
|
+
*/
|
66
|
+
|
67
|
+
template <typename Type>
|
68
|
+
class Complex {
|
69
|
+
public:
|
70
|
+
// The real and immaginary parts of the complex number.
|
71
|
+
Type r;
|
72
|
+
Type i;
|
73
|
+
|
74
|
+
/*
|
75
|
+
* Default constructor.
|
76
|
+
*/
|
77
|
+
inline Complex(Type real = 0, Type imaginary = 0) : r(real), i(imaginary) {}
|
78
|
+
|
79
|
+
/*
|
80
|
+
* Copy constructors.
|
81
|
+
*/
|
82
|
+
template <typename ComplexType>
|
83
|
+
inline Complex(const Complex<ComplexType>& other) : r(other.r), i(other.i) {}
|
84
|
+
|
85
|
+
template <typename IntType, typename = typename std::enable_if<std::is_integral<IntType>::value>::type>
|
86
|
+
inline Complex(const Rational<IntType>& other) : r(Type(other.n) / Type(other.d)), i(0) {}
|
87
|
+
|
88
|
+
/*
|
89
|
+
* Complex conjugate function -- creates a copy, but inverted.
|
90
|
+
*/
|
91
|
+
inline Complex<Type> conjugate() const {
|
92
|
+
return Complex<Type>(this->r, -(this->i));
|
93
|
+
}
|
94
|
+
|
95
|
+
/*
|
96
|
+
* Complex inverse function -- creates a copy, but inverted.
|
97
|
+
*
|
98
|
+
* FIXME: Check that this doesn't duplicate functionality of NativeType / Complex<Type>
|
99
|
+
*/
|
100
|
+
inline Complex<Type> inverse() const {
|
101
|
+
Complex<Type> conj = conjugate();
|
102
|
+
Type denom = this->r * this->r + this->i * this->i;
|
103
|
+
return Complex<Type>(conj.r / denom, conj.i / denom);
|
104
|
+
}
|
105
|
+
|
106
|
+
|
107
|
+
|
108
|
+
/*
|
109
|
+
* Binary operator definitions for various types.
|
110
|
+
*/
|
111
|
+
|
112
|
+
////////////////////////////////
|
113
|
+
// Complex-Complex Operations //
|
114
|
+
////////////////////////////////
|
115
|
+
|
116
|
+
template <typename OtherType>
|
117
|
+
inline Complex<Type> operator+(const Complex<OtherType>& other) const {
|
118
|
+
return Complex<Type>(this->r + other.r, this->i + other.i);
|
119
|
+
}
|
120
|
+
|
121
|
+
template <typename OtherType>
|
122
|
+
inline Complex<Type>& operator+=(const Complex<OtherType>& other) {
|
123
|
+
this->r += other.r;
|
124
|
+
this->i += other.i;
|
125
|
+
return *this;
|
126
|
+
}
|
127
|
+
|
128
|
+
template <typename OtherType>
|
129
|
+
inline Complex<Type> operator-(const Complex<OtherType>& other) const {
|
130
|
+
return Complex<Type>(this->r - other.r, this->i - other.i);
|
131
|
+
}
|
132
|
+
|
133
|
+
template <typename OtherType>
|
134
|
+
inline Complex<Type> operator*(const Complex<OtherType>& other) const {
|
135
|
+
return Complex<Type>(this->r * other.r - this->i * other.i, this->r * other.i - this->i * other.r);
|
136
|
+
}
|
137
|
+
|
138
|
+
template <typename OtherType>
|
139
|
+
inline Complex<Type>& operator*=(const Complex<OtherType>& other) {
|
140
|
+
this->r = this->r * other.r - this->i * other.i;
|
141
|
+
this->i = this->r * other.i - this->i * other.r;
|
142
|
+
return *this;
|
143
|
+
}
|
144
|
+
|
145
|
+
template <typename OtherType>
|
146
|
+
inline Complex<Type> operator/(const Complex<OtherType>& other) const {
|
147
|
+
Type new_r, new_i;
|
148
|
+
Type denom = this->i * this->i + other.r * other.r;
|
149
|
+
|
150
|
+
new_r = (this->r * other.r + this->i * other.i) / denom;
|
151
|
+
new_i = (this->r * other.i - this->i * other.r) / denom;
|
152
|
+
|
153
|
+
return Complex<Type>(new_r, new_i);
|
154
|
+
}
|
155
|
+
|
156
|
+
template <typename OtherType>
|
157
|
+
inline bool operator<(const Complex<OtherType>& other) const {
|
158
|
+
return (this->r < other.r) || ((this->r <= other.r) && (this->i < other.i));
|
159
|
+
}
|
160
|
+
|
161
|
+
template <typename OtherType>
|
162
|
+
inline bool operator>(const Complex<OtherType>& other) const {
|
163
|
+
return (this->r > other.r) || ((this->r >= other.r) && (this->i > other.i));
|
164
|
+
}
|
165
|
+
|
166
|
+
template <typename OtherType>
|
167
|
+
inline bool operator==(const Complex<OtherType>& other) const {
|
168
|
+
return FP_EQUAL(this->r, other.r) && FP_EQUAL(this->i, other.i);
|
169
|
+
}
|
170
|
+
|
171
|
+
template <typename OtherType>
|
172
|
+
inline bool operator!=(const Complex<OtherType>& other) const {
|
173
|
+
return !(*this == other);
|
174
|
+
}
|
175
|
+
|
176
|
+
template <typename OtherType>
|
177
|
+
inline bool operator<=(const Complex<OtherType>& other) const {
|
178
|
+
return (*this < other) || (*this == other);
|
179
|
+
}
|
180
|
+
|
181
|
+
template <typename OtherType>
|
182
|
+
inline bool operator>=(const Complex<OtherType>& other) const {
|
183
|
+
return (*this > other) || (*this == other);
|
184
|
+
}
|
185
|
+
|
186
|
+
template <typename OtherType>
|
187
|
+
inline operator Complex<OtherType> () const {
|
188
|
+
return Complex<OtherType>((OtherType)this->r, (OtherType)this->i);
|
189
|
+
}
|
190
|
+
|
191
|
+
/////////////////////////////////
|
192
|
+
// Complex-Rational Operations //
|
193
|
+
/////////////////////////////////
|
194
|
+
|
195
|
+
template <typename RationalType>
|
196
|
+
inline Complex<Type> operator+(const Rational<RationalType>& other) const {
|
197
|
+
return *this + Complex<Type>(other);
|
198
|
+
}
|
199
|
+
|
200
|
+
template <typename RationalType>
|
201
|
+
inline Complex<Type> operator-(const Rational<RationalType>& other) const {
|
202
|
+
return *this * Complex<Type>(other);
|
203
|
+
}
|
204
|
+
|
205
|
+
template <typename RationalType>
|
206
|
+
inline Complex<Type> operator*(const Rational<RationalType>& other) const {
|
207
|
+
return *this * Complex<Type>(other);
|
208
|
+
}
|
209
|
+
|
210
|
+
template <typename RationalType>
|
211
|
+
inline Complex<Type> operator/(const Rational<RationalType>& other) const {
|
212
|
+
return *this / Complex<Type>(other);
|
213
|
+
}
|
214
|
+
|
215
|
+
template <typename RationalType, typename = typename std::enable_if<std::is_integral<RationalType>::value>::type>
|
216
|
+
inline bool operator!=(const Rational<RationalType>& other) const {
|
217
|
+
return *this != Complex<Type>(other);
|
218
|
+
}
|
219
|
+
|
220
|
+
template <typename RationalType, typename = typename std::enable_if<std::is_integral<RationalType>::value>::type>
|
221
|
+
inline bool operator==(const Rational<RationalType>& other) const {
|
222
|
+
return *this == Complex<Type>(other);
|
223
|
+
}
|
224
|
+
|
225
|
+
///////////////////////////////
|
226
|
+
// Complex-Native Operations //
|
227
|
+
///////////////////////////////
|
228
|
+
|
229
|
+
template <typename NativeType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
|
230
|
+
inline Complex<Type> operator+(const NativeType& other) const {
|
231
|
+
return *this + Complex<Type>(other);
|
232
|
+
}
|
233
|
+
|
234
|
+
template <typename NativeType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
|
235
|
+
inline Complex<Type> operator-(const NativeType& other) const {
|
236
|
+
return *this - Complex<Type>(other);
|
237
|
+
}
|
238
|
+
|
239
|
+
template <typename NativeType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
|
240
|
+
inline Complex<Type> operator*(const NativeType& other) const {
|
241
|
+
return *this * Complex<Type>(other);
|
242
|
+
}
|
243
|
+
|
244
|
+
template <typename NativeType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
|
245
|
+
inline Complex<Type> operator/(const NativeType& other) const {
|
246
|
+
return *this / Complex<Type>(other);
|
247
|
+
}
|
248
|
+
|
249
|
+
template <typename NativeType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
|
250
|
+
inline bool operator<(const NativeType& other) const {
|
251
|
+
return *this < Complex<Type>(other);
|
252
|
+
}
|
253
|
+
|
254
|
+
template <typename NativeType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
|
255
|
+
inline bool operator>(const NativeType& other) const {
|
256
|
+
return *this > Complex<Type>(other);
|
257
|
+
}
|
258
|
+
|
259
|
+
template <typename NativeType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
|
260
|
+
inline bool operator==(const NativeType& other) const {
|
261
|
+
return *this == Complex<Type>(other);
|
262
|
+
}
|
263
|
+
|
264
|
+
template <typename NativeType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
|
265
|
+
inline bool operator!=(const NativeType& other) const {
|
266
|
+
return *this != Complex<Type>(other);
|
267
|
+
}
|
268
|
+
|
269
|
+
template <typename NativeType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
|
270
|
+
inline bool operator<=(const NativeType& other) const {
|
271
|
+
return *this <= Complex<Type>(other);
|
272
|
+
}
|
273
|
+
|
274
|
+
template <typename NativeType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
|
275
|
+
inline bool operator>=(const NativeType& other) const {
|
276
|
+
return *this >= Complex<Type>(other);
|
277
|
+
}
|
278
|
+
|
279
|
+
template <typename NativeType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
|
280
|
+
inline operator NativeType () const {
|
281
|
+
return (NativeType)this->r;
|
282
|
+
}
|
283
|
+
};
|
284
|
+
|
285
|
+
|
286
|
+
/////////////////////////////////
|
287
|
+
// Rational-Complex Operations //
|
288
|
+
/////////////////////////////////
|
289
|
+
|
290
|
+
|
291
|
+
template <typename IntType, typename ComplexType, typename = typename std::enable_if<std::is_integral<IntType>::value>::type>
|
292
|
+
inline bool operator==(const Rational<IntType>& left, const Complex<ComplexType>& right) {
|
293
|
+
return Complex<ComplexType>(left) == right;
|
294
|
+
}
|
295
|
+
|
296
|
+
template <typename IntType, typename ComplexType, typename = typename std::enable_if<std::is_integral<IntType>::value>::type>
|
297
|
+
inline bool operator!=(const Rational<IntType>& left, const Complex<ComplexType>& right) {
|
298
|
+
return Complex<ComplexType>(left) != right;
|
299
|
+
}
|
300
|
+
|
301
|
+
|
302
|
+
///////////////////////////////
|
303
|
+
// Native-Complex Operations //
|
304
|
+
///////////////////////////////
|
305
|
+
|
306
|
+
template <typename NativeType, typename ComplexType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
|
307
|
+
inline Complex<ComplexType> operator+(const NativeType& left, const Complex<ComplexType>& right) {
|
308
|
+
return Complex<ComplexType>(left) + right;
|
309
|
+
}
|
310
|
+
|
311
|
+
template <typename NativeType, typename ComplexType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
|
312
|
+
inline Complex<ComplexType> operator-(const NativeType& left, const Complex<ComplexType>& right) {
|
313
|
+
return Complex<ComplexType>(left) - right;
|
314
|
+
}
|
315
|
+
|
316
|
+
template <typename NativeType, typename ComplexType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
|
317
|
+
inline Complex<ComplexType> operator*(const NativeType& left, const Complex<ComplexType>& right) {
|
318
|
+
return Complex<ComplexType>(left) * right;
|
319
|
+
}
|
320
|
+
|
321
|
+
template <typename NativeType, typename ComplexType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
|
322
|
+
inline Complex<ComplexType> operator/(const NativeType& left, const Complex<ComplexType>& right) {
|
323
|
+
return Complex<ComplexType>(left) / right;
|
324
|
+
}
|
325
|
+
|
326
|
+
template <typename NativeType, typename ComplexType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
|
327
|
+
inline bool operator<(const NativeType left, const Complex<ComplexType>& right) {
|
328
|
+
return Complex<ComplexType>(left) < right;
|
329
|
+
}
|
330
|
+
|
331
|
+
template <typename NativeType, typename ComplexType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
|
332
|
+
inline bool operator>(const NativeType left, const Complex<ComplexType>& right) {
|
333
|
+
return Complex<ComplexType>(left) > right;
|
334
|
+
}
|
335
|
+
|
336
|
+
template <typename NativeType, typename ComplexType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
|
337
|
+
inline bool operator==(const NativeType left, const Complex<ComplexType>& right) {
|
338
|
+
return Complex<ComplexType>(left) == right;
|
339
|
+
}
|
340
|
+
|
341
|
+
template <typename NativeType, typename ComplexType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
|
342
|
+
inline bool operator!=(const NativeType left, const Complex<ComplexType>& right) {
|
343
|
+
return Complex<ComplexType>(left) != right;
|
344
|
+
}
|
345
|
+
|
346
|
+
template <typename NativeType, typename ComplexType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
|
347
|
+
inline bool operator<=(const NativeType left, const Complex<ComplexType>& right) {
|
348
|
+
return Complex<ComplexType>(left) <= right;
|
349
|
+
}
|
350
|
+
|
351
|
+
template <typename NativeType, typename ComplexType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
|
352
|
+
inline bool operator>=(const NativeType left, const Complex<ComplexType>& right) {
|
353
|
+
return Complex<ComplexType>(left) >= right;
|
354
|
+
}
|
355
|
+
|
356
|
+
template <typename Type>
|
357
|
+
inline std::ostream& operator<<(std::ostream& out, const Complex<Type>& rhs) {
|
358
|
+
out << "(" << rhs.r << "," << rhs.i << "i)" << std::flush;
|
359
|
+
return out;
|
360
|
+
}
|
361
|
+
|
362
|
+
} // end of namespace nm
|
363
|
+
|
364
|
+
namespace std {
|
365
|
+
template <typename FloatType, typename = typename std::enable_if<std::is_floating_point<FloatType>::value>::type>
|
366
|
+
nm::Complex<FloatType> abs(const nm::Complex<FloatType>& value) {
|
367
|
+
return nm::Complex<FloatType>(value.r < 0 ? -value.r : value.r,
|
368
|
+
value.i < 0 ? -value.i : value.i);
|
369
|
+
}
|
370
|
+
}
|
371
|
+
|
372
|
+
#endif // COMPLEX_H
|
@@ -0,0 +1,275 @@
|
|
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
|
+
// == data.cpp
|
25
|
+
//
|
26
|
+
// Functions and data for dealing the data types.
|
27
|
+
|
28
|
+
/*
|
29
|
+
* Standard Includes
|
30
|
+
*/
|
31
|
+
|
32
|
+
#include <ruby.h>
|
33
|
+
|
34
|
+
/*
|
35
|
+
* Project Includes
|
36
|
+
*/
|
37
|
+
|
38
|
+
#include "types.h"
|
39
|
+
|
40
|
+
#include "data.h"
|
41
|
+
|
42
|
+
/*
|
43
|
+
* Macros
|
44
|
+
*/
|
45
|
+
|
46
|
+
/*
|
47
|
+
* Global Variables
|
48
|
+
*/
|
49
|
+
|
50
|
+
extern "C" {
|
51
|
+
|
52
|
+
const char* const DTYPE_NAMES[nm::NUM_DTYPES] = {
|
53
|
+
"byte",
|
54
|
+
"int8",
|
55
|
+
"int16",
|
56
|
+
"int32",
|
57
|
+
"int64",
|
58
|
+
"float32",
|
59
|
+
"float64",
|
60
|
+
"complex64",
|
61
|
+
"complex128",
|
62
|
+
"rational32",
|
63
|
+
"rational64",
|
64
|
+
"rational128",
|
65
|
+
"object"
|
66
|
+
};
|
67
|
+
|
68
|
+
const char* const ITYPE_NAMES[nm::NUM_ITYPES] = {
|
69
|
+
"uint8",
|
70
|
+
"uint16",
|
71
|
+
"uint32",
|
72
|
+
"uint64"
|
73
|
+
};
|
74
|
+
|
75
|
+
const size_t DTYPE_SIZES[nm::NUM_DTYPES] = {
|
76
|
+
sizeof(uint8_t),
|
77
|
+
sizeof(int8_t),
|
78
|
+
sizeof(int16_t),
|
79
|
+
sizeof(int32_t),
|
80
|
+
sizeof(int64_t),
|
81
|
+
sizeof(float32_t),
|
82
|
+
sizeof(float64_t),
|
83
|
+
sizeof(nm::Complex64),
|
84
|
+
sizeof(nm::Complex128),
|
85
|
+
sizeof(nm::Rational32),
|
86
|
+
sizeof(nm::Rational64),
|
87
|
+
sizeof(nm::Rational128),
|
88
|
+
sizeof(nm::RubyObject)
|
89
|
+
};
|
90
|
+
|
91
|
+
const size_t ITYPE_SIZES[nm::NUM_ITYPES] = {
|
92
|
+
sizeof(uint8_t),
|
93
|
+
sizeof(uint16_t),
|
94
|
+
sizeof(uint32_t),
|
95
|
+
sizeof(uint64_t),
|
96
|
+
};
|
97
|
+
|
98
|
+
const dtype_t Upcast[nm::NUM_DTYPES][nm::NUM_DTYPES] = {
|
99
|
+
{ BYTE, INT8, INT16, INT32, INT64, FLOAT32, FLOAT64, COMPLEX64, COMPLEX128, RATIONAL32, RATIONAL64, RATIONAL128, RUBYOBJ},
|
100
|
+
{ INT8, INT8, INT16, INT32, INT64, FLOAT32, FLOAT64, COMPLEX64, COMPLEX128, RATIONAL32, RATIONAL64, RATIONAL128, RUBYOBJ},
|
101
|
+
{ INT16, INT16, INT16, INT32, INT64, FLOAT32, FLOAT64, COMPLEX64, COMPLEX128, RATIONAL32, RATIONAL64, RATIONAL128, RUBYOBJ},
|
102
|
+
{ INT32, INT32, INT32, INT32, INT64, FLOAT32, FLOAT64, COMPLEX64, COMPLEX128, RATIONAL32, RATIONAL64, RATIONAL128, RUBYOBJ},
|
103
|
+
{ INT64, INT64, INT64, INT64, INT64, FLOAT32, FLOAT64, COMPLEX64, COMPLEX128, RATIONAL32, RATIONAL64, RATIONAL128, RUBYOBJ},
|
104
|
+
{ FLOAT32, FLOAT32, FLOAT32, FLOAT32, FLOAT32, FLOAT32, FLOAT64, COMPLEX64, COMPLEX128, FLOAT64, FLOAT64, FLOAT64, RUBYOBJ},
|
105
|
+
{ FLOAT64, FLOAT64, FLOAT64, FLOAT64, FLOAT64, FLOAT64, FLOAT64, COMPLEX128, COMPLEX128, FLOAT64, FLOAT64, FLOAT64, RUBYOBJ},
|
106
|
+
{ COMPLEX64, COMPLEX64, COMPLEX64, COMPLEX64, COMPLEX64, COMPLEX64, COMPLEX128, COMPLEX64, COMPLEX128, COMPLEX64, COMPLEX64, COMPLEX64, RUBYOBJ},
|
107
|
+
{ COMPLEX128, COMPLEX128, COMPLEX128, COMPLEX128, COMPLEX128, COMPLEX128, COMPLEX128, COMPLEX128, COMPLEX128, COMPLEX128, COMPLEX128, COMPLEX128, RUBYOBJ},
|
108
|
+
{ RATIONAL32, RATIONAL32, RATIONAL32, RATIONAL32, RATIONAL32, FLOAT64, FLOAT64, COMPLEX64, COMPLEX128, RATIONAL32, RATIONAL64, RATIONAL128, RUBYOBJ},
|
109
|
+
{ RATIONAL64, RATIONAL64, RATIONAL64, RATIONAL64, RATIONAL64, FLOAT64, FLOAT64, COMPLEX64, COMPLEX128, RATIONAL64, RATIONAL64, RATIONAL128, RUBYOBJ},
|
110
|
+
{ RATIONAL128, RATIONAL128, RATIONAL128, RATIONAL128, RATIONAL128, FLOAT64, FLOAT64, COMPLEX64, COMPLEX128, RATIONAL128, RATIONAL128, RATIONAL128, RUBYOBJ},
|
111
|
+
{ RUBYOBJ, RUBYOBJ, RUBYOBJ, RUBYOBJ, RUBYOBJ, RUBYOBJ, RUBYOBJ, RUBYOBJ, RUBYOBJ, RUBYOBJ, RUBYOBJ, RUBYOBJ, RUBYOBJ}
|
112
|
+
};
|
113
|
+
|
114
|
+
|
115
|
+
/*
|
116
|
+
* Forward Declarations
|
117
|
+
*/
|
118
|
+
|
119
|
+
/*
|
120
|
+
* Functions
|
121
|
+
*/
|
122
|
+
|
123
|
+
/*
|
124
|
+
* Converts a RubyObject
|
125
|
+
*/
|
126
|
+
void rubyval_to_cval(VALUE val, dtype_t dtype, void* loc) {
|
127
|
+
using namespace nm;
|
128
|
+
switch (dtype) {
|
129
|
+
case BYTE:
|
130
|
+
*reinterpret_cast<uint8_t*>(loc) = static_cast<uint8_t>(RubyObject(val));
|
131
|
+
break;
|
132
|
+
|
133
|
+
case INT8:
|
134
|
+
*reinterpret_cast<int8_t*>(loc) = static_cast<int8_t>(RubyObject(val));
|
135
|
+
break;
|
136
|
+
|
137
|
+
case INT16:
|
138
|
+
*reinterpret_cast<int16_t*>(loc) = static_cast<int16_t>(RubyObject(val));
|
139
|
+
break;
|
140
|
+
|
141
|
+
case INT32:
|
142
|
+
*reinterpret_cast<int32_t*>(loc) = static_cast<int32_t>(RubyObject(val));
|
143
|
+
break;
|
144
|
+
|
145
|
+
case INT64:
|
146
|
+
*reinterpret_cast<int64_t*>(loc) = static_cast<int64_t>(RubyObject(val));
|
147
|
+
break;
|
148
|
+
|
149
|
+
case FLOAT32:
|
150
|
+
*reinterpret_cast<float32_t*>(loc) = static_cast<float32_t>(RubyObject(val));
|
151
|
+
break;
|
152
|
+
|
153
|
+
case FLOAT64:
|
154
|
+
*reinterpret_cast<float64_t*>(loc) = static_cast<float64_t>(RubyObject(val));
|
155
|
+
break;
|
156
|
+
|
157
|
+
case COMPLEX64:
|
158
|
+
*reinterpret_cast<Complex64*>(loc) = RubyObject(val).to<Complex64>();
|
159
|
+
break;
|
160
|
+
|
161
|
+
case COMPLEX128:
|
162
|
+
*reinterpret_cast<Complex128*>(loc) = RubyObject(val).to<Complex64>();
|
163
|
+
break;
|
164
|
+
|
165
|
+
case RATIONAL32:
|
166
|
+
*reinterpret_cast<Rational32*>(loc) = RubyObject(val).to<Rational32>();
|
167
|
+
break;
|
168
|
+
|
169
|
+
case RATIONAL64:
|
170
|
+
*reinterpret_cast<Rational64*>(loc) = RubyObject(val).to<Rational64>();
|
171
|
+
break;
|
172
|
+
|
173
|
+
case RATIONAL128:
|
174
|
+
*reinterpret_cast<Rational128*>(loc) = RubyObject(val).to<Rational128>();
|
175
|
+
break;
|
176
|
+
|
177
|
+
case RUBYOBJ:
|
178
|
+
*reinterpret_cast<VALUE*>(loc) = RubyObject(val).rval;
|
179
|
+
//rb_raise(rb_eTypeError, "Attempting a bad conversion from a Ruby value.");
|
180
|
+
break;
|
181
|
+
|
182
|
+
default:
|
183
|
+
rb_raise(rb_eTypeError, "Attempting a bad conversion from a Ruby value.");
|
184
|
+
break;
|
185
|
+
}
|
186
|
+
}
|
187
|
+
|
188
|
+
/*
|
189
|
+
* Create a RubyObject from a regular C value (given a dtype). Does not return a VALUE! To get a VALUE, you need to
|
190
|
+
* look at the rval property of what this function returns.
|
191
|
+
*/
|
192
|
+
nm::RubyObject rubyobj_from_cval(void* val, dtype_t dtype) {
|
193
|
+
using namespace nm;
|
194
|
+
switch (dtype) {
|
195
|
+
case BYTE:
|
196
|
+
return RubyObject(*reinterpret_cast<uint8_t*>(val));
|
197
|
+
|
198
|
+
case INT8:
|
199
|
+
return RubyObject(*reinterpret_cast<int8_t*>(val));
|
200
|
+
|
201
|
+
case INT16:
|
202
|
+
return RubyObject(*reinterpret_cast<int16_t*>(val));
|
203
|
+
|
204
|
+
case INT32:
|
205
|
+
return RubyObject(*reinterpret_cast<int32_t*>(val));
|
206
|
+
|
207
|
+
case INT64:
|
208
|
+
return RubyObject(*reinterpret_cast<int64_t*>(val));
|
209
|
+
|
210
|
+
case FLOAT32:
|
211
|
+
return RubyObject(*reinterpret_cast<float32_t*>(val));
|
212
|
+
|
213
|
+
case FLOAT64:
|
214
|
+
return RubyObject(*reinterpret_cast<float64_t*>(val));
|
215
|
+
|
216
|
+
case COMPLEX64:
|
217
|
+
return RubyObject(*reinterpret_cast<Complex64*>(val));
|
218
|
+
|
219
|
+
case COMPLEX128:
|
220
|
+
return RubyObject(*reinterpret_cast<Complex128*>(val));
|
221
|
+
|
222
|
+
case RATIONAL32:
|
223
|
+
return RubyObject(*reinterpret_cast<Rational32*>(val));
|
224
|
+
|
225
|
+
case RATIONAL64:
|
226
|
+
return RubyObject(*reinterpret_cast<Rational64*>(val));
|
227
|
+
|
228
|
+
case RATIONAL128:
|
229
|
+
return RubyObject(*reinterpret_cast<Rational128*>(val));
|
230
|
+
|
231
|
+
default:
|
232
|
+
rb_raise(nm_eDataTypeError, "Conversion to RubyObject requested from unknown/invalid data type (did you try to convert from a VALUE?)");
|
233
|
+
}
|
234
|
+
return Qnil;
|
235
|
+
}
|
236
|
+
|
237
|
+
|
238
|
+
/*
|
239
|
+
* Convert from itype instead of dtype
|
240
|
+
*/
|
241
|
+
nm::RubyObject rubyobj_from_cval_by_itype(void* val, itype_t itype) {
|
242
|
+
using namespace nm;
|
243
|
+
switch (itype) {
|
244
|
+
case UINT8:
|
245
|
+
return RubyObject(*reinterpret_cast<uint8_t*>(val));
|
246
|
+
|
247
|
+
case UINT16:
|
248
|
+
return RubyObject((int16_t)(*reinterpret_cast<uint16_t*>(val)));
|
249
|
+
|
250
|
+
case UINT32:
|
251
|
+
return RubyObject((int32_t)(*reinterpret_cast<uint32_t*>(val)));
|
252
|
+
|
253
|
+
case UINT64:
|
254
|
+
return RubyObject((int64_t)(*reinterpret_cast<uint64_t*>(val)));
|
255
|
+
|
256
|
+
default:
|
257
|
+
rb_raise(nm_eDataTypeError, "Conversion to RubyObject requested from unknown data type");
|
258
|
+
}
|
259
|
+
return Qnil;
|
260
|
+
}
|
261
|
+
|
262
|
+
/*
|
263
|
+
* Allocate and return a piece of data of the correct dtype, converted from a
|
264
|
+
* given RubyObject.
|
265
|
+
*/
|
266
|
+
void* rubyobj_to_cval(VALUE val, dtype_t dtype) {
|
267
|
+
size_t size = DTYPE_SIZES[dtype];
|
268
|
+
void* ret_val = ALLOC_N(char, size);
|
269
|
+
|
270
|
+
rubyval_to_cval(val, dtype, ret_val);
|
271
|
+
|
272
|
+
return ret_val;
|
273
|
+
}
|
274
|
+
|
275
|
+
} // end of extern "C" block
|