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.
Files changed (91) hide show
  1. data/.gitignore +27 -0
  2. data/.rspec +2 -0
  3. data/Gemfile +3 -5
  4. data/Guardfile +6 -0
  5. data/History.txt +33 -0
  6. data/Manifest.txt +41 -38
  7. data/README.rdoc +88 -11
  8. data/Rakefile +35 -53
  9. data/ext/nmatrix/data/complex.h +372 -0
  10. data/ext/nmatrix/data/data.cpp +275 -0
  11. data/ext/nmatrix/data/data.h +707 -0
  12. data/ext/nmatrix/data/rational.h +421 -0
  13. data/ext/nmatrix/data/ruby_object.h +446 -0
  14. data/ext/nmatrix/extconf.rb +101 -51
  15. data/ext/nmatrix/new_extconf.rb +56 -0
  16. data/ext/nmatrix/nmatrix.cpp +1609 -0
  17. data/ext/nmatrix/nmatrix.h +265 -849
  18. data/ext/nmatrix/ruby_constants.cpp +134 -0
  19. data/ext/nmatrix/ruby_constants.h +103 -0
  20. data/ext/nmatrix/storage/common.cpp +70 -0
  21. data/ext/nmatrix/storage/common.h +170 -0
  22. data/ext/nmatrix/storage/dense.cpp +665 -0
  23. data/ext/nmatrix/storage/dense.h +116 -0
  24. data/ext/nmatrix/storage/list.cpp +1088 -0
  25. data/ext/nmatrix/storage/list.h +129 -0
  26. data/ext/nmatrix/storage/storage.cpp +658 -0
  27. data/ext/nmatrix/storage/storage.h +99 -0
  28. data/ext/nmatrix/storage/yale.cpp +1601 -0
  29. data/ext/nmatrix/storage/yale.h +208 -0
  30. data/ext/nmatrix/ttable_helper.rb +126 -0
  31. data/ext/nmatrix/{yale/smmp1_header.template.c → types.h} +36 -9
  32. data/ext/nmatrix/util/io.cpp +295 -0
  33. data/ext/nmatrix/util/io.h +117 -0
  34. data/ext/nmatrix/util/lapack.h +1175 -0
  35. data/ext/nmatrix/util/math.cpp +557 -0
  36. data/ext/nmatrix/util/math.h +1363 -0
  37. data/ext/nmatrix/util/sl_list.cpp +475 -0
  38. data/ext/nmatrix/util/sl_list.h +255 -0
  39. data/ext/nmatrix/util/util.h +78 -0
  40. data/lib/nmatrix/blas.rb +70 -0
  41. data/lib/nmatrix/io/mat5_reader.rb +567 -0
  42. data/lib/nmatrix/io/mat_reader.rb +162 -0
  43. data/lib/{string.rb → nmatrix/monkeys.rb} +49 -2
  44. data/lib/nmatrix/nmatrix.rb +199 -0
  45. data/lib/nmatrix/nvector.rb +103 -0
  46. data/lib/nmatrix/version.rb +27 -0
  47. data/lib/nmatrix.rb +22 -230
  48. data/nmatrix.gemspec +59 -0
  49. data/scripts/mac-brew-gcc.sh +47 -0
  50. data/spec/4x4_sparse.mat +0 -0
  51. data/spec/4x5_dense.mat +0 -0
  52. data/spec/blas_spec.rb +47 -0
  53. data/spec/elementwise_spec.rb +164 -0
  54. data/spec/io_spec.rb +60 -0
  55. data/spec/lapack_spec.rb +52 -0
  56. data/spec/math_spec.rb +96 -0
  57. data/spec/nmatrix_spec.rb +93 -89
  58. data/spec/nmatrix_yale_spec.rb +52 -36
  59. data/spec/nvector_spec.rb +1 -1
  60. data/spec/slice_spec.rb +257 -0
  61. data/spec/spec_helper.rb +51 -0
  62. data/spec/utm5940.mtx +83844 -0
  63. metadata +113 -71
  64. data/.autotest +0 -23
  65. data/.gemtest +0 -0
  66. data/ext/nmatrix/cblas.c +0 -150
  67. data/ext/nmatrix/dense/blas_header.template.c +0 -52
  68. data/ext/nmatrix/dense/elementwise.template.c +0 -107
  69. data/ext/nmatrix/dense/gemm.template.c +0 -159
  70. data/ext/nmatrix/dense/gemv.template.c +0 -130
  71. data/ext/nmatrix/dense/rationalmath.template.c +0 -68
  72. data/ext/nmatrix/dense.c +0 -307
  73. data/ext/nmatrix/depend +0 -18
  74. data/ext/nmatrix/generator/syntax_tree.rb +0 -481
  75. data/ext/nmatrix/generator.rb +0 -594
  76. data/ext/nmatrix/list.c +0 -774
  77. data/ext/nmatrix/nmatrix.c +0 -1977
  78. data/ext/nmatrix/rational.c +0 -98
  79. data/ext/nmatrix/yale/complexmath.template.c +0 -71
  80. data/ext/nmatrix/yale/elementwise.template.c +0 -46
  81. data/ext/nmatrix/yale/elementwise_op.template.c +0 -73
  82. data/ext/nmatrix/yale/numbmm.template.c +0 -94
  83. data/ext/nmatrix/yale/smmp1.template.c +0 -21
  84. data/ext/nmatrix/yale/smmp2.template.c +0 -43
  85. data/ext/nmatrix/yale/smmp2_header.template.c +0 -46
  86. data/ext/nmatrix/yale/sort_columns.template.c +0 -56
  87. data/ext/nmatrix/yale/symbmm.template.c +0 -54
  88. data/ext/nmatrix/yale/transp.template.c +0 -68
  89. data/ext/nmatrix/yale.c +0 -726
  90. data/lib/array.rb +0 -67
  91. 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
@@ -22,11 +22,13 @@
22
22
  #
23
23
  # == extconf.rb
24
24
  #
25
- # This file mostly derived from NArray.
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
- hfile = open(file, "w")
63
- for line in $defs
64
- line =~ /^-D(.*)/
65
- hfile.printf "#define %s 1\n", $1
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(" ") #-BENCHMARK for comparing transp
85
-
86
- srcs = %w(
87
- nmatrix
88
- list
89
- dense
90
- yale
91
- dfuncs
92
- smmp1
93
- smmp2
94
- cblas
95
- blas
96
- rational
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
- header = "stdint.h"
101
- unless have_header(header)
102
- header = "sys/types.h"
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
- have_type("u_int8_t", header)
109
- have_type("uint8_t", header)
110
- have_type("u_int16_t", header)
111
- have_type("uint16_t", header)
112
- have_type("int16_t", header)
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
- # dir_config("cblas")
125
- # dir_config("atlas")
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
- find_header("cblas.h", "/usr/local/include", "/usr/local/atlas/include")
129
+ have_header("cblas.h")
130
130
 
131
- have_library("f2c")
132
- have_header("f2c.h")
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
- $libs += " -lcblas -latlas "
136
+ #CONFIG['CXX'] = 'clang++'
137
+ CONFIG['CXX'] = 'g++'
136
138
 
137
- $objs = srcs.collect{|i| i+".o" }
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
- $CFLAGS += " -O0"
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