nmatrix 0.1.0 → 0.2.0

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 (78) hide show
  1. checksums.yaml +4 -4
  2. data/ext/nmatrix/data/complex.h +20 -55
  3. data/ext/nmatrix/data/data.cpp +11 -44
  4. data/ext/nmatrix/data/data.h +174 -311
  5. data/ext/nmatrix/data/meta.h +1 -7
  6. data/ext/nmatrix/data/ruby_object.h +3 -85
  7. data/ext/nmatrix/extconf.rb +2 -73
  8. data/ext/nmatrix/math.cpp +170 -813
  9. data/ext/nmatrix/math/asum.h +2 -25
  10. data/ext/nmatrix/math/{inc.h → cblas_enums.h} +11 -22
  11. data/ext/nmatrix/math/cblas_templates_core.h +507 -0
  12. data/ext/nmatrix/math/gemm.h +2 -32
  13. data/ext/nmatrix/math/gemv.h +1 -35
  14. data/ext/nmatrix/math/getrf.h +21 -6
  15. data/ext/nmatrix/math/getrs.h +0 -8
  16. data/ext/nmatrix/math/imax.h +0 -22
  17. data/ext/nmatrix/math/long_dtype.h +0 -3
  18. data/ext/nmatrix/math/math.h +11 -337
  19. data/ext/nmatrix/math/nrm2.h +2 -23
  20. data/ext/nmatrix/math/rot.h +1 -25
  21. data/ext/nmatrix/math/rotg.h +4 -13
  22. data/ext/nmatrix/math/scal.h +0 -22
  23. data/ext/nmatrix/math/trsm.h +0 -55
  24. data/ext/nmatrix/math/util.h +148 -0
  25. data/ext/nmatrix/nmatrix.cpp +0 -14
  26. data/ext/nmatrix/nmatrix.h +92 -84
  27. data/ext/nmatrix/ruby_constants.cpp +0 -2
  28. data/ext/nmatrix/ruby_constants.h +0 -2
  29. data/ext/nmatrix/ruby_nmatrix.c +86 -45
  30. data/ext/nmatrix/storage/dense/dense.cpp +1 -7
  31. data/ext/nmatrix/storage/storage.h +0 -1
  32. data/ext/nmatrix/ttable_helper.rb +0 -6
  33. data/ext/nmatrix/util/io.cpp +1 -1
  34. data/lib/nmatrix.rb +1 -19
  35. data/lib/nmatrix/blas.rb +33 -11
  36. data/lib/nmatrix/io/market.rb +3 -3
  37. data/lib/nmatrix/lapack_core.rb +181 -0
  38. data/lib/nmatrix/lapack_plugin.rb +44 -0
  39. data/lib/nmatrix/math.rb +382 -131
  40. data/lib/nmatrix/monkeys.rb +2 -3
  41. data/lib/nmatrix/nmatrix.rb +166 -13
  42. data/lib/nmatrix/shortcuts.rb +72 -7
  43. data/lib/nmatrix/version.rb +2 -2
  44. data/spec/00_nmatrix_spec.rb +154 -5
  45. data/spec/02_slice_spec.rb +2 -6
  46. data/spec/03_nmatrix_monkeys_spec.rb +7 -1
  47. data/spec/blas_spec.rb +60 -33
  48. data/spec/homogeneous_spec.rb +10 -10
  49. data/spec/lapack_core_spec.rb +482 -0
  50. data/spec/math_spec.rb +436 -52
  51. data/spec/shortcuts_spec.rb +28 -4
  52. data/spec/spec_helper.rb +14 -2
  53. data/spec/utm5940.mtx +83844 -0
  54. metadata +49 -76
  55. data/.gitignore +0 -27
  56. data/.rspec +0 -2
  57. data/.travis.yml +0 -15
  58. data/CONTRIBUTING.md +0 -82
  59. data/Gemfile +0 -2
  60. data/History.txt +0 -677
  61. data/LICENSE.txt +0 -23
  62. data/Manifest.txt +0 -92
  63. data/README.rdoc +0 -150
  64. data/Rakefile +0 -216
  65. data/ext/nmatrix/data/rational.h +0 -440
  66. data/ext/nmatrix/math/geev.h +0 -82
  67. data/ext/nmatrix/math/ger.h +0 -96
  68. data/ext/nmatrix/math/gesdd.h +0 -80
  69. data/ext/nmatrix/math/gesvd.h +0 -78
  70. data/ext/nmatrix/math/getf2.h +0 -86
  71. data/ext/nmatrix/math/getri.h +0 -108
  72. data/ext/nmatrix/math/potrs.h +0 -129
  73. data/ext/nmatrix/math/swap.h +0 -52
  74. data/lib/nmatrix/lapack.rb +0 -240
  75. data/nmatrix.gemspec +0 -55
  76. data/scripts/mac-brew-gcc.sh +0 -50
  77. data/scripts/mac-mavericks-brew-gcc.sh +0 -22
  78. data/spec/lapack_spec.rb +0 -459
@@ -59,6 +59,8 @@
59
59
  #ifndef NRM2_H
60
60
  # define NRM2_H
61
61
 
62
+ #include "math/long_dtype.h"
63
+
62
64
 
63
65
  namespace nm { namespace math {
64
66
 
@@ -71,7 +73,6 @@ namespace nm { namespace math {
71
73
  * double -> double
72
74
  * complex64 -> float or double
73
75
  * complex128 -> double
74
- * rational -> rational
75
76
  */
76
77
  template <typename ReturnDType, typename DType>
77
78
  ReturnDType nrm2(const int N, const DType* X, const int incX) {
@@ -98,27 +99,6 @@ ReturnDType nrm2(const int N, const DType* X, const int incX) {
98
99
  }
99
100
 
100
101
 
101
- #if defined HAVE_CBLAS_H || defined HAVE_ATLAS_CBLAS_H
102
- template <>
103
- inline float nrm2(const int N, const float* X, const int incX) {
104
- return cblas_snrm2(N, X, incX);
105
- }
106
-
107
- template <>
108
- inline double nrm2(const int N, const double* X, const int incX) {
109
- return cblas_dnrm2(N, X, incX);
110
- }
111
-
112
- template <>
113
- inline float nrm2(const int N, const Complex64* X, const int incX) {
114
- return cblas_scnrm2(N, X, incX);
115
- }
116
-
117
- template <>
118
- inline double nrm2(const int N, const Complex128* X, const int incX) {
119
- return cblas_dznrm2(N, X, incX);
120
- }
121
- #else
122
102
  template <typename FloatDType>
123
103
  static inline void nrm2_complex_helper(const FloatDType& xr, const FloatDType& xi, double& scale, double& ssq) {
124
104
  double absx = std::abs(xr);
@@ -167,7 +147,6 @@ double nrm2(const int N, const Complex128* X, const int incX) {
167
147
 
168
148
  return scale * std::sqrt( ssq );
169
149
  }
170
- #endif
171
150
 
172
151
  template <typename ReturnDType, typename DType>
173
152
  inline void cblas_nrm2(const int N, const void* X, const int incX, void* result) {
@@ -61,9 +61,6 @@
61
61
 
62
62
  namespace nm { namespace math {
63
63
 
64
- // FIXME: This is not working properly for rational numbers. Do we need some kind of symbolic
65
- // type to handle square roots?
66
-
67
64
 
68
65
  // TODO: Test this to see if it works properly on complex. ATLAS has a separate algorithm for complex, which looks like
69
66
  // TODO: it may actually be the same one.
@@ -108,27 +105,6 @@ inline void rot(const int N, DType* X, const int incX, DType* Y, const int incY,
108
105
  }
109
106
  }
110
107
 
111
- template <>
112
- inline void rot(const int N, float* X, const int incX, float* Y, const int incY, const float c, const float s) {
113
- cblas_srot(N, X, incX, Y, incY, (float)c, (float)s);
114
- }
115
-
116
- template <>
117
- inline void rot(const int N, double* X, const int incX, double* Y, const int incY, const double c, const double s) {
118
- cblas_drot(N, X, incX, Y, incY, c, s);
119
- }
120
-
121
- template <>
122
- inline void rot(const int N, Complex64* X, const int incX, Complex64* Y, const int incY, const float c, const float s) {
123
- cblas_csrot(N, X, incX, Y, incY, c, s);
124
- }
125
-
126
- template <>
127
- inline void rot(const int N, Complex128* X, const int incX, Complex128* Y, const int incY, const double c, const double s) {
128
- cblas_zdrot(N, X, incX, Y, incY, c, s);
129
- }
130
-
131
-
132
108
  template <typename DType, typename CSDType>
133
109
  inline void cblas_rot(const int N, void* X, const int incX, void* Y, const int incY, const void* c, const void* s) {
134
110
  rot<DType,CSDType>(N, reinterpret_cast<DType*>(X), incX, reinterpret_cast<DType*>(Y), incY,
@@ -138,4 +114,4 @@ inline void cblas_rot(const int N, void* X, const int incX, void* Y, const int i
138
114
 
139
115
  } } //nm::math
140
116
 
141
- #endif // ROT_H
117
+ #endif // ROT_H
@@ -84,26 +84,17 @@ inline void rotg(DType* a, DType* b, DType* c, DType* s) {
84
84
  }
85
85
  }
86
86
 
87
- template <>
88
- inline void rotg(float* a, float* b, float* c, float* s) {
89
- cblas_srotg(a, b, c, s);
90
- }
91
-
92
- template <>
93
- inline void rotg(double* a, double* b, double* c, double* s) {
94
- cblas_drotg(a, b, c, s);
95
- }
96
-
97
87
  template <>
98
88
  inline void rotg(Complex64* a, Complex64* b, Complex64* c, Complex64* s) {
99
- cblas_crotg(reinterpret_cast<void*>(a), reinterpret_cast<void*>(b), reinterpret_cast<void*>(c), reinterpret_cast<void*>(s));
89
+ rb_raise(rb_eNotImpError, "BLAS not available, and existing template requires modification for complex");
100
90
  }
101
91
 
102
92
  template <>
103
93
  inline void rotg(Complex128* a, Complex128* b, Complex128* c, Complex128* s) {
104
- cblas_zrotg(reinterpret_cast<void*>(a), reinterpret_cast<void*>(b), reinterpret_cast<void*>(c), reinterpret_cast<void*>(s));
94
+ rb_raise(rb_eNotImpError, "BLAS not available, and existing template requires modification for complex");
105
95
  }
106
96
 
97
+
107
98
  template <typename DType>
108
99
  inline void cblas_rotg(void* a, void* b, void* c, void* s) {
109
100
  rotg<DType>(reinterpret_cast<DType*>(a), reinterpret_cast<DType*>(b), reinterpret_cast<DType*>(c), reinterpret_cast<DType*>(s));
@@ -112,4 +103,4 @@ inline void cblas_rotg(void* a, void* b, void* c, void* s) {
112
103
 
113
104
  } } //nm::math
114
105
 
115
- #endif // ROTG_H
106
+ #endif // ROTG_H
@@ -58,28 +58,6 @@ inline void scal(const int n, const DType scalar, DType* x, const int incx) {
58
58
  }
59
59
  }
60
60
 
61
- #if defined HAVE_CBLAS_H || defined HAVE_ATLAS_CBLAS_H
62
- template <>
63
- inline void scal(const int n, const float scalar, float* x, const int incx) {
64
- cblas_sscal(n, scalar, x, incx);
65
- }
66
-
67
- template <>
68
- inline void scal(const int n, const double scalar, double* x, const int incx) {
69
- cblas_dscal(n, scalar, x, incx);
70
- }
71
-
72
- template <>
73
- inline void scal(const int n, const Complex64 scalar, Complex64* x, const int incx) {
74
- cblas_cscal(n, (const void*)(&scalar), (void*)(x), incx);
75
- }
76
-
77
- template <>
78
- inline void scal(const int n, const Complex128 scalar, Complex128* x, const int incx) {
79
- cblas_zscal(n, (const void*)(&scalar), (void*)(x), incx);
80
- }
81
- #endif
82
-
83
61
  /*
84
62
  * Function signature conversion for LAPACK's scal function.
85
63
  */
@@ -59,14 +59,6 @@
59
59
  #define TRSM_H
60
60
 
61
61
 
62
- extern "C" {
63
- #if defined HAVE_CBLAS_H
64
- #include <cblas.h>
65
- #elif defined HAVE_ATLAS_CBLAS_H
66
- #include <atlas/cblas.h>
67
- #endif
68
- }
69
-
70
62
  namespace nm { namespace math {
71
63
 
72
64
 
@@ -336,52 +328,5 @@ inline void trsm(const enum CBLAS_ORDER order,
336
328
 
337
329
  }
338
330
 
339
-
340
- template <>
341
- inline void trsm(const enum CBLAS_ORDER order, const enum CBLAS_SIDE side, const enum CBLAS_UPLO uplo,
342
- const enum CBLAS_TRANSPOSE trans_a, const enum CBLAS_DIAG diag,
343
- const int m, const int n, const float alpha, const float* a,
344
- const int lda, float* b, const int ldb)
345
- {
346
- cblas_strsm(order, side, uplo, trans_a, diag, m, n, alpha, a, lda, b, ldb);
347
- }
348
-
349
- template <>
350
- inline void trsm(const enum CBLAS_ORDER order, const enum CBLAS_SIDE side, const enum CBLAS_UPLO uplo,
351
- const enum CBLAS_TRANSPOSE trans_a, const enum CBLAS_DIAG diag,
352
- const int m, const int n, const double alpha, const double* a,
353
- const int lda, double* b, const int ldb)
354
- {
355
- /* using std::cerr;
356
- using std::endl;
357
- cerr << "(row-major) dtrsm: " << (side == CblasLeft ? "left " : "right ")
358
- << (uplo == CblasUpper ? "upper " : "lower ")
359
- << (trans_a == CblasTrans ? "trans " : "notrans ")
360
- << (diag == CblasNonUnit ? "nonunit " : "unit ")
361
- << m << " " << n << " " << alpha << " a " << lda << " b " << ldb << endl;
362
- */
363
- cblas_dtrsm(order, side, uplo, trans_a, diag, m, n, alpha, a, lda, b, ldb);
364
- }
365
-
366
-
367
- template <>
368
- inline void trsm(const enum CBLAS_ORDER order, const enum CBLAS_SIDE side, const enum CBLAS_UPLO uplo,
369
- const enum CBLAS_TRANSPOSE trans_a, const enum CBLAS_DIAG diag,
370
- const int m, const int n, const Complex64 alpha, const Complex64* a,
371
- const int lda, Complex64* b, const int ldb)
372
- {
373
- cblas_ctrsm(order, side, uplo, trans_a, diag, m, n, (const void*)(&alpha), (const void*)(a), lda, (void*)(b), ldb);
374
- }
375
-
376
- template <>
377
- inline void trsm(const enum CBLAS_ORDER order, const enum CBLAS_SIDE side, const enum CBLAS_UPLO uplo,
378
- const enum CBLAS_TRANSPOSE trans_a, const enum CBLAS_DIAG diag,
379
- const int m, const int n, const Complex128 alpha, const Complex128* a,
380
- const int lda, Complex128* b, const int ldb)
381
- {
382
- cblas_ztrsm(order, side, uplo, trans_a, diag, m, n, (const void*)(&alpha), (const void*)(a), lda, (void*)(b), ldb);
383
- }
384
-
385
-
386
331
  } } // namespace nm::math
387
332
  #endif // TRSM_H
@@ -0,0 +1,148 @@
1
+ /////////////////////////////////////////////////////////////////////
2
+ // = NMatrix
3
+ //
4
+ // A linear algebra library for scientific computation in Ruby.
5
+ // NMatrix is part of SciRuby.
6
+ //
7
+ // NMatrix was originally inspired by and derived from NArray, by
8
+ // Masahiro Tanaka: http://narray.rubyforge.org
9
+ //
10
+ // == Copyright Information
11
+ //
12
+ // SciRuby is Copyright (c) 2010 - 2014, Ruby Science Foundation
13
+ // NMatrix is Copyright (c) 2012 - 2014, John Woods and the Ruby Science Foundation
14
+ //
15
+ // Please see LICENSE.txt for additional copyright notices.
16
+ //
17
+ // == Contributing
18
+ //
19
+ // By contributing source code to SciRuby, you agree to be bound by
20
+ // our Contributor Agreement:
21
+ //
22
+ // * https://github.com/SciRuby/sciruby/wiki/Contributor-Agreement
23
+ //
24
+ // == util.h
25
+ //
26
+ // Collect a few utility functions which convert ruby symbols into arguments
27
+ // that CBLAS or LAPACK can understand: either enum's for CBLAS or char's
28
+ // for LAPACK.
29
+ //
30
+
31
+ #ifndef UTIL_H
32
+ #define UTIL_H
33
+
34
+ /* Interprets cblas argument which could be any of false/:no_transpose, :transpose, or :complex_conjugate,
35
+ * into an enum recognized by cblas.
36
+ *
37
+ * Called by nm_cblas_gemm -- basically inline.
38
+ *
39
+ */
40
+ static inline enum CBLAS_TRANSPOSE blas_transpose_sym(VALUE op) {
41
+ if (op == Qfalse || rb_to_id(op) == nm_rb_no_transpose) return CblasNoTrans;
42
+ else if (rb_to_id(op) == nm_rb_transpose) return CblasTrans;
43
+ else if (rb_to_id(op) == nm_rb_complex_conjugate) return CblasConjTrans;
44
+ else rb_raise(rb_eArgError, "Expected false, :transpose, or :complex_conjugate");
45
+ return CblasNoTrans;
46
+ }
47
+
48
+ /* Interprets transpose argument which could be any of false/:no_transpose, :transpose, or :complex_conjugate,
49
+ * into an character recognized by LAPACKE. LAPACKE uses a different system than CBLAS for this.
50
+ *
51
+ */
52
+ static inline char lapacke_transpose_sym(VALUE op) {
53
+ if (op == Qfalse || rb_to_id(op) == nm_rb_no_transpose) return 'N';
54
+ else if (rb_to_id(op) == nm_rb_transpose) return 'T';
55
+ else if (rb_to_id(op) == nm_rb_complex_conjugate) return 'C';
56
+ else rb_raise(rb_eArgError, "Expected false, :transpose, or :complex_conjugate");
57
+ return 'N';
58
+ }
59
+
60
+ /*
61
+ * Interprets cblas argument which could be :left or :right
62
+ *
63
+ * Called by nm_cblas_trsm -- basically inline
64
+ */
65
+ static inline enum CBLAS_SIDE blas_side_sym(VALUE op) {
66
+ ID op_id = rb_to_id(op);
67
+ if (op_id == nm_rb_left) return CblasLeft;
68
+ if (op_id == nm_rb_right) return CblasRight;
69
+ rb_raise(rb_eArgError, "Expected :left or :right for side argument");
70
+ return CblasLeft;
71
+ }
72
+
73
+ /*
74
+ * Interprets cblas argument which could be :upper or :lower
75
+ *
76
+ * Called by nm_cblas_trsm -- basically inline
77
+ */
78
+ static inline enum CBLAS_UPLO blas_uplo_sym(VALUE op) {
79
+ ID op_id = rb_to_id(op);
80
+ if (op_id == nm_rb_upper) return CblasUpper;
81
+ if (op_id == nm_rb_lower) return CblasLower;
82
+ rb_raise(rb_eArgError, "Expected :upper or :lower for uplo argument");
83
+ return CblasUpper;
84
+ }
85
+
86
+ /*
87
+ * Interprets argument which could be :upper or :lower for LAPACKE
88
+ *
89
+ * Called by nm_cblas_trsm -- basically inline
90
+ */
91
+ static inline char lapacke_uplo_sym(VALUE op) {
92
+ ID op_id = rb_to_id(op);
93
+ if (op_id == nm_rb_upper) return 'U';
94
+ if (op_id == nm_rb_lower) return 'L';
95
+ rb_raise(rb_eArgError, "Expected :upper or :lower for uplo argument");
96
+ return 'U';
97
+ }
98
+
99
+ /*
100
+ * Interprets cblas argument which could be :unit (true) or :nonunit (false or anything other than true/:unit)
101
+ *
102
+ * Called by nm_cblas_trsm -- basically inline
103
+ */
104
+ static inline enum CBLAS_DIAG blas_diag_sym(VALUE op) {
105
+ if (rb_to_id(op) == nm_rb_unit || op == Qtrue) return CblasUnit;
106
+ return CblasNonUnit;
107
+ }
108
+
109
+ /*
110
+ * Interprets cblas argument which could be :row or :col
111
+ *
112
+ * This function, unlike the other ones, works for LAPACKE as well as for CBLAS/CLAPACK.
113
+ * Although LAPACKE calls this an int instead of a enum, the magic values are the same
114
+ * (101 for row-major, 102 for column-major).
115
+ */
116
+ static inline enum CBLAS_ORDER blas_order_sym(VALUE op) {
117
+ if (rb_to_id(op) == rb_intern("row") || rb_to_id(op) == rb_intern("row_major")) return CblasRowMajor;
118
+ else if (rb_to_id(op) == rb_intern("col") || rb_to_id(op) == rb_intern("col_major") ||
119
+ rb_to_id(op) == rb_intern("column") || rb_to_id(op) == rb_intern("column_major")) return CblasColMajor;
120
+ rb_raise(rb_eArgError, "Expected :row or :col for order argument");
121
+ return CblasRowMajor;
122
+ }
123
+
124
+ /*
125
+ * Interprets lapack jobu and jobvt arguments, for which LAPACK needs character values A, S, O, or N.
126
+ *
127
+ * Called by lapack_gesvd -- basically inline. svd stands for singular value decomposition.
128
+ */
129
+ static inline char lapack_svd_job_sym(VALUE op) {
130
+ if (rb_to_id(op) == rb_intern("all") || rb_to_id(op) == rb_intern("a")) return 'A';
131
+ else if (rb_to_id(op) == rb_intern("return") || rb_to_id(op) == rb_intern("s")) return 'S';
132
+ else if (rb_to_id(op) == rb_intern("overwrite") || rb_to_id(op) == rb_intern("o")) return 'O';
133
+ else if (rb_to_id(op) == rb_intern("none") || rb_to_id(op) == rb_intern("n")) return 'N';
134
+ else rb_raise(rb_eArgError, "Expected :all, :return, :overwrite, :none (or :a, :s, :o, :n, respectively)");
135
+ return 'a';
136
+ }
137
+
138
+ /*
139
+ * Interprets lapack jobvl and jobvr arguments, for which LAPACK needs character values N or V.
140
+ *
141
+ * Called by lapack_geev -- basically inline. evd stands for eigenvalue decomposition.
142
+ */
143
+ static inline char lapack_evd_job_sym(VALUE op) {
144
+ if (op == Qfalse || op == Qnil || rb_to_id(op) == rb_intern("n")) return 'N';
145
+ else return 'V';
146
+ }
147
+
148
+ #endif
@@ -31,20 +31,6 @@
31
31
  * Standard Includes
32
32
  */
33
33
 
34
- extern "C" {
35
- #if defined HAVE_CBLAS_H
36
- #include <cblas.h>
37
- #elif defined HAVE_ATLAS_CBLAS_H
38
- #include <atlas/cblas.h>
39
- #endif
40
-
41
- #if defined HAVE_CLAPACK_H
42
- #include <clapack.h>
43
- #elif defined HAVE_ATLAS_CLAPACK_H
44
- #include <atlas/clapack.h>
45
- #endif
46
- }
47
-
48
34
  #include <ruby.h>
49
35
  #include <algorithm> // std::min
50
36
  #include <fstream>
@@ -43,14 +43,14 @@
43
43
  #endif
44
44
 
45
45
  #ifdef BENCHMARK
46
- // SOURCE: http://stackoverflow.com/questions/2349776/how-can-i-benchmark-a-c-program-easily
46
+ // SOURCE: http://stackoverflow.com/questions/2349776/how-can-i-benchmark-a-c-program-easily
47
47
  #ifdef __cplusplus
48
48
  #include <sys/ctime>
49
49
  #include <sys/cresource>
50
50
  #else
51
51
  #include <sys/time.h>
52
52
  #include <sys/resource.h>
53
- #endif
53
+ #endif
54
54
  #endif
55
55
 
56
56
  #ifdef __cplusplus
@@ -64,24 +64,24 @@
64
64
  #define RUBY_ZERO INT2FIX(0)
65
65
 
66
66
  #ifndef SIZEOF_INT
67
- #error SIZEOF_INT undefined
67
+ #error SIZEOF_INT undefined
68
68
  #else
69
- #if SIZEOF_INT == 8
70
- #define DEFAULT_DTYPE INT64
71
- #define SIZE_T INT64
72
- #else
73
- #if SIZEOF_INT == 4
74
- #define DEFAULT_DTYPE INT32
75
- #define SIZE_T INT32
76
- #else
77
- #if SIZEOF_INT == 2
78
- #define DEFAULT_DTYPE INT16
79
- #define SIZE_T INT16
80
- #else
81
- #error Unhandled SIZEOF_INT -- please #define SIZE_T and DEFAULT_DTYPE manually.
82
- #endif
83
- #endif
84
- #endif
69
+ #if SIZEOF_INT == 8
70
+ #define DEFAULT_DTYPE INT64
71
+ #define SIZE_T INT64
72
+ #else
73
+ #if SIZEOF_INT == 4
74
+ #define DEFAULT_DTYPE INT32
75
+ #define SIZE_T INT32
76
+ #else
77
+ #if SIZEOF_INT == 2
78
+ #define DEFAULT_DTYPE INT16
79
+ #define SIZE_T INT16
80
+ #else
81
+ #error Unhandled SIZEOF_INT -- please #define SIZE_T and DEFAULT_DTYPE manually.
82
+ #endif
83
+ #endif
84
+ #endif
85
85
  #endif
86
86
 
87
87
  /*
@@ -119,27 +119,27 @@
119
119
  */
120
120
 
121
121
  //opening portion -- this allows unregistering any objects in use before returning
122
- #define RETURN_SIZED_ENUMERATOR_PRE do { \
123
- if (!rb_block_given_p()) {
122
+ #define RETURN_SIZED_ENUMERATOR_PRE do { \
123
+ if (!rb_block_given_p()) {
124
124
 
125
125
  //remaining portion
126
- #ifdef RUBY_2
127
- #ifndef RETURN_SIZED_ENUMERATOR
128
- #undef RETURN_SIZED_ENUMERATOR
129
- // Ruby 2.0 and higher has rb_enumeratorize_with_size instead of rb_enumeratorize.
130
- // We want to support both in the simplest way possible.
131
- #define RETURN_SIZED_ENUMERATOR(obj, argc, argv, size_fn) \
126
+ #ifdef RUBY_2
127
+ #ifndef RETURN_SIZED_ENUMERATOR
128
+ #undef RETURN_SIZED_ENUMERATOR
129
+ // Ruby 2.0 and higher has rb_enumeratorize_with_size instead of rb_enumeratorize.
130
+ // We want to support both in the simplest way possible.
131
+ #define RETURN_SIZED_ENUMERATOR(obj, argc, argv, size_fn) \
132
132
  return rb_enumeratorize_with_size((obj), ID2SYM(rb_frame_this_func()), (argc), (argv), (size_fn)); \
133
133
  } \
134
134
  } while (0)
135
- #endif
136
- #else
137
- #undef RETURN_SIZED_ENUMERATOR
138
- #define RETURN_SIZED_ENUMERATOR(obj, argc, argv, size_fn) \
139
- return rb_enumeratorize((obj), ID2SYM(rb_frame_this_func()), (argc), (argv)); \
135
+ #endif
136
+ #else
137
+ #undef RETURN_SIZED_ENUMERATOR
138
+ #define RETURN_SIZED_ENUMERATOR(obj, argc, argv, size_fn) \
139
+ return rb_enumeratorize((obj), ID2SYM(rb_frame_this_func()), (argc), (argv)); \
140
140
  } \
141
141
  } while (0)
142
- #endif
142
+ #endif
143
143
 
144
144
  #define NM_DECL_ENUM(enum_type, name) nm::enum_type name
145
145
  #define NM_DECL_STRUCT(type, name) type name;
@@ -149,8 +149,8 @@
149
149
  size_t dim; \
150
150
  size_t* shape; \
151
151
  size_t* offset; \
152
- int count; \
153
- STORAGE* src;
152
+ int count; \
153
+ STORAGE* src;
154
154
 
155
155
  #define NM_DEF_STORAGE_CHILD_STRUCT_PRE(name) struct name : STORAGE {
156
156
  #define NM_DEF_STORAGE_STRUCT_POST(name) };
@@ -180,10 +180,10 @@
180
180
  size_t dim; \
181
181
  size_t* shape; \
182
182
  size_t* offset; \
183
- int count; \
184
- STORAGE* src;
183
+ int count; \
184
+ NM_DECL_STRUCT(STORAGE*, src);
185
185
  #define NM_DEF_STORAGE_CHILD_STRUCT_PRE(name) typedef struct NM_ ## name { \
186
- NM_DEF_STORAGE_ELEMENTS;
186
+ NM_DEF_STORAGE_ELEMENTS;
187
187
 
188
188
  #define NM_DEF_STORAGE_STRUCT_POST(name) } NM_ ## name;
189
189
 
@@ -207,7 +207,7 @@
207
207
  * Types
208
208
  */
209
209
 
210
- #define NM_NUM_DTYPES 13 // data/data.h
210
+ #define NM_NUM_DTYPES 10 // data/data.h
211
211
  #define NM_NUM_STYPES 3 // storage/storage.h
212
212
 
213
213
  //#ifdef __cplusplus
@@ -220,19 +220,16 @@ NM_DEF_ENUM(stype_t, DENSE_STORE = 0,
220
220
  YALE_STORE = 2);
221
221
 
222
222
  /* Data Type */
223
- NM_DEF_ENUM(dtype_t, BYTE = 0, // unsigned char
224
- INT8 = 1, // char
225
- INT16 = 2, // short
226
- INT32 = 3, // int
227
- INT64 = 4, // long
228
- FLOAT32 = 5, // float
229
- FLOAT64 = 6, // double
230
- COMPLEX64 = 7, // Complex64 class
231
- COMPLEX128 = 8, // Complex128 class
232
- RATIONAL32 = 9, // Rational32 class
233
- RATIONAL64 = 10, // Rational64 class
234
- RATIONAL128 = 11, // Rational128 class
235
- RUBYOBJ = 12); // Ruby VALUE type
223
+ NM_DEF_ENUM(dtype_t, BYTE = 0, // unsigned char
224
+ INT8 = 1, // char
225
+ INT16 = 2, // short
226
+ INT32 = 3, // int
227
+ INT64 = 4, // long
228
+ FLOAT32 = 5, // float
229
+ FLOAT64 = 6, // double
230
+ COMPLEX64 = 7, // Complex64 class
231
+ COMPLEX128 = 8, // Complex128 class
232
+ RUBYOBJ = 9); // Ruby VALUE type
236
233
 
237
234
  NM_DEF_ENUM(symm_t, NONSYMM = 0,
238
235
  SYMM = 1,
@@ -250,16 +247,16 @@ NM_DEF_STORAGE_STRUCT;
250
247
 
251
248
  /* Dense Storage */
252
249
  NM_DEF_STORAGE_CHILD_STRUCT_PRE(DENSE_STORAGE); // struct DENSE_STORAGE : STORAGE {
253
- void* elements; // should go first to align with void* a in yale and NODE* first in list.
254
- size_t* stride;
250
+ void* elements; // should go first to align with void* a in yale and NODE* first in list.
251
+ size_t* stride;
255
252
  NM_DEF_STORAGE_STRUCT_POST(DENSE_STORAGE); // };
256
253
 
257
254
  /* Yale Storage */
258
255
  NM_DEF_STORAGE_CHILD_STRUCT_PRE(YALE_STORAGE);
259
- void* a; // should go first
260
- size_t ndnz; // Strictly non-diagonal non-zero count!
261
- size_t capacity;
262
- size_t* ija;
256
+ void* a; // should go first
257
+ size_t ndnz; // Strictly non-diagonal non-zero count!
258
+ size_t capacity;
259
+ size_t* ija;
263
260
  NM_DEF_STORAGE_STRUCT_POST(YALE_STORAGE);
264
261
 
265
262
  // FIXME: NODE and LIST should be put in some kind of namespace or something, at least in C++.
@@ -275,9 +272,9 @@ NM_DEF_STRUCT_POST(LIST); // };
275
272
 
276
273
  /* List-of-Lists Storage */
277
274
  NM_DEF_STORAGE_CHILD_STRUCT_PRE(LIST_STORAGE); // struct LIST_STORAGE : STORAGE {
278
- // List storage specific elements.
279
- void* default_val;
280
- NM_DECL_STRUCT(LIST*, rows); // LIST* rows;
275
+ // List storage specific elements.
276
+ void* default_val;
277
+ NM_DECL_STRUCT(LIST*, rows); // LIST* rows;
281
278
  NM_DEF_STORAGE_STRUCT_POST(LIST_STORAGE); // };
282
279
 
283
280
 
@@ -329,7 +326,7 @@ NM_DEF_STRUCT_POST(NM_GC_HOLDER); // };
329
326
  #define NM_DENSE_COUNT(val) (nm_storage_count_max_elements(NM_STORAGE_DENSE(val)))
330
327
  #define NM_DENSE_ELEMENTS(val) (NM_STORAGE_DENSE(val)->elements)
331
328
  #define NM_SIZEOF_DTYPE(val) (DTYPE_SIZES[NM_DTYPE(val)])
332
- #define NM_REF(val,slice) (RefFuncs[NM_STYPE(val)]( NM_STORAGE(val), slice, NM_SIZEOF_DTYPE(val) ))
329
+ #define NM_REF(val,slice) (RefFuncs[NM_STYPE(val)]( NM_STORAGE(val), slice, NM_SIZEOF_DTYPE(val) ))
333
330
 
334
331
  #define NM_MAX(a,b) (((a)>(b))?(a):(b))
335
332
  #define NM_MIN(a,b) (((a)>(b))?(b):(a))
@@ -348,8 +345,8 @@ NM_DEF_STRUCT_POST(NM_GC_HOLDER); // };
348
345
  (rb_obj_is_kind_of(obj, cNVector) == Qtrue)
349
346
 
350
347
  #define RB_P(OBJ) \
351
- rb_funcall(rb_stderr, rb_intern("print"), 1, rb_funcall(OBJ, rb_intern("object_id"), 0)); \
352
- rb_funcall(rb_stderr, rb_intern("puts"), 1, rb_funcall(OBJ, rb_intern("inspect"), 0));
348
+ rb_funcall(rb_stderr, rb_intern("print"), 1, rb_funcall(OBJ, rb_intern("object_id"), 0)); \
349
+ rb_funcall(rb_stderr, rb_intern("puts"), 1, rb_funcall(OBJ, rb_intern("inspect"), 0));
353
350
 
354
351
 
355
352
  #ifdef __cplusplus
@@ -358,43 +355,54 @@ typedef VALUE (*METHOD)(...);
358
355
  //}; // end of namespace nm
359
356
  #endif
360
357
 
358
+ // In the init code below, we need to use NMATRIX for c++ and NM_NMATRIX for c
359
+ // this macro chooses the correct one:
360
+ #ifdef __cplusplus
361
+ #define _NMATRIX NMATRIX
362
+ #define _STORAGE STORAGE
363
+ #else
364
+ #define _NMATRIX NM_NMATRIX
365
+ #define _STORAGE NM_STORAGE
366
+ #endif
367
+
361
368
  /*
362
369
  * Functions
363
370
  */
364
371
 
365
372
  #ifdef __cplusplus
366
-
367
373
  extern "C" {
368
374
  #endif
369
375
 
370
- void Init_nmatrix();
371
-
372
- // External API
373
- VALUE rb_nmatrix_dense_create(NM_DECL_ENUM(dtype_t, dtype), size_t* shape, size_t dim, void* elements, size_t length);
374
- VALUE rb_nvector_dense_create(NM_DECL_ENUM(dtype_t, dtype), void* elements, size_t length);
376
+ void Init_nmatrix();
377
+ // External API
378
+ VALUE rb_nmatrix_dense_create(NM_DECL_ENUM(dtype_t, dtype), size_t* shape, size_t dim, void* elements, size_t length);
379
+ VALUE rb_nvector_dense_create(NM_DECL_ENUM(dtype_t, dtype), void* elements, size_t length);
375
380
 
376
- NM_DECL_ENUM(dtype_t, nm_dtype_guess(VALUE)); // (This is a function)
377
- NM_DECL_ENUM(dtype_t, nm_dtype_min(VALUE));
381
+ NM_DECL_ENUM(dtype_t, nm_dtype_guess(VALUE)); // (This is a function)
382
+ NM_DECL_ENUM(dtype_t, nm_dtype_min(VALUE));
378
383
 
379
384
  // Non-API functions needed by other cpp files.
380
- NMATRIX* nm_create(NM_DECL_ENUM(stype_t, stype), STORAGE* storage);
381
- NMATRIX* nm_cast_with_ctype_args(NMATRIX* self, NM_DECL_ENUM(stype_t, new_stype), NM_DECL_ENUM(dtype_t, new_dtype), void* init_ptr);
382
- VALUE nm_cast(VALUE self, VALUE new_stype_symbol, VALUE new_dtype_symbol, VALUE init);
383
- void nm_mark(NMATRIX* mat);
384
- void nm_delete(NMATRIX* mat);
385
- void nm_delete_ref(NMATRIX* mat);
385
+ _NMATRIX* nm_create(NM_DECL_ENUM(stype_t, stype), _STORAGE* storage);
386
+ _NMATRIX* nm_cast_with_ctype_args(_NMATRIX* self, NM_DECL_ENUM(stype_t, new_stype), NM_DECL_ENUM(dtype_t, new_dtype), void* init_ptr);
387
+ VALUE nm_cast(VALUE self, VALUE new_stype_symbol, VALUE new_dtype_symbol, VALUE init);
388
+ void nm_mark(_NMATRIX* mat);
389
+ void nm_delete(_NMATRIX* mat);
390
+ void nm_delete_ref(_NMATRIX* mat);
386
391
  void nm_register_values(VALUE* vals, size_t n);
387
392
  void nm_register_value(VALUE* val);
388
393
  void nm_unregister_value(VALUE* val);
389
394
  void nm_unregister_values(VALUE* vals, size_t n);
390
- void nm_register_storage(NM_DECL_ENUM(stype_t, stype), const STORAGE* storage);
391
- void nm_unregister_storage(NM_DECL_ENUM(stype_t, stype), const STORAGE* storage);
392
- void nm_register_nmatrix(NMATRIX* nmatrix);
393
- void nm_unregister_nmatrix(NMATRIX* nmatrix);
394
- void nm_completely_unregister_value(VALUE* val);
395
+ void nm_register_storage(NM_DECL_ENUM(stype_t, stype), const _STORAGE* storage);
396
+ void nm_unregister_storage(NM_DECL_ENUM(stype_t, stype), const _STORAGE* storage);
397
+ void nm_register_nmatrix(_NMATRIX* nmatrix);
398
+ void nm_unregister_nmatrix(_NMATRIX* nmatrix);
399
+ void nm_completely_unregister_value(VALUE* val);
400
+
395
401
  #ifdef __cplusplus
396
402
  }
397
-
398
403
  #endif
399
404
 
405
+ #undef _NMATRIX
406
+ #undef _STORAGE
407
+
400
408
  #endif // NMATRIX_H