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.
- checksums.yaml +4 -4
- data/ext/nmatrix/data/complex.h +20 -55
- data/ext/nmatrix/data/data.cpp +11 -44
- data/ext/nmatrix/data/data.h +174 -311
- data/ext/nmatrix/data/meta.h +1 -7
- data/ext/nmatrix/data/ruby_object.h +3 -85
- data/ext/nmatrix/extconf.rb +2 -73
- data/ext/nmatrix/math.cpp +170 -813
- data/ext/nmatrix/math/asum.h +2 -25
- data/ext/nmatrix/math/{inc.h → cblas_enums.h} +11 -22
- data/ext/nmatrix/math/cblas_templates_core.h +507 -0
- data/ext/nmatrix/math/gemm.h +2 -32
- data/ext/nmatrix/math/gemv.h +1 -35
- data/ext/nmatrix/math/getrf.h +21 -6
- data/ext/nmatrix/math/getrs.h +0 -8
- data/ext/nmatrix/math/imax.h +0 -22
- data/ext/nmatrix/math/long_dtype.h +0 -3
- data/ext/nmatrix/math/math.h +11 -337
- data/ext/nmatrix/math/nrm2.h +2 -23
- data/ext/nmatrix/math/rot.h +1 -25
- data/ext/nmatrix/math/rotg.h +4 -13
- data/ext/nmatrix/math/scal.h +0 -22
- data/ext/nmatrix/math/trsm.h +0 -55
- data/ext/nmatrix/math/util.h +148 -0
- data/ext/nmatrix/nmatrix.cpp +0 -14
- data/ext/nmatrix/nmatrix.h +92 -84
- data/ext/nmatrix/ruby_constants.cpp +0 -2
- data/ext/nmatrix/ruby_constants.h +0 -2
- data/ext/nmatrix/ruby_nmatrix.c +86 -45
- data/ext/nmatrix/storage/dense/dense.cpp +1 -7
- data/ext/nmatrix/storage/storage.h +0 -1
- data/ext/nmatrix/ttable_helper.rb +0 -6
- data/ext/nmatrix/util/io.cpp +1 -1
- data/lib/nmatrix.rb +1 -19
- data/lib/nmatrix/blas.rb +33 -11
- data/lib/nmatrix/io/market.rb +3 -3
- data/lib/nmatrix/lapack_core.rb +181 -0
- data/lib/nmatrix/lapack_plugin.rb +44 -0
- data/lib/nmatrix/math.rb +382 -131
- data/lib/nmatrix/monkeys.rb +2 -3
- data/lib/nmatrix/nmatrix.rb +166 -13
- data/lib/nmatrix/shortcuts.rb +72 -7
- data/lib/nmatrix/version.rb +2 -2
- data/spec/00_nmatrix_spec.rb +154 -5
- data/spec/02_slice_spec.rb +2 -6
- data/spec/03_nmatrix_monkeys_spec.rb +7 -1
- data/spec/blas_spec.rb +60 -33
- data/spec/homogeneous_spec.rb +10 -10
- data/spec/lapack_core_spec.rb +482 -0
- data/spec/math_spec.rb +436 -52
- data/spec/shortcuts_spec.rb +28 -4
- data/spec/spec_helper.rb +14 -2
- data/spec/utm5940.mtx +83844 -0
- metadata +49 -76
- data/.gitignore +0 -27
- data/.rspec +0 -2
- data/.travis.yml +0 -15
- data/CONTRIBUTING.md +0 -82
- data/Gemfile +0 -2
- data/History.txt +0 -677
- data/LICENSE.txt +0 -23
- data/Manifest.txt +0 -92
- data/README.rdoc +0 -150
- data/Rakefile +0 -216
- data/ext/nmatrix/data/rational.h +0 -440
- data/ext/nmatrix/math/geev.h +0 -82
- data/ext/nmatrix/math/ger.h +0 -96
- data/ext/nmatrix/math/gesdd.h +0 -80
- data/ext/nmatrix/math/gesvd.h +0 -78
- data/ext/nmatrix/math/getf2.h +0 -86
- data/ext/nmatrix/math/getri.h +0 -108
- data/ext/nmatrix/math/potrs.h +0 -129
- data/ext/nmatrix/math/swap.h +0 -52
- data/lib/nmatrix/lapack.rb +0 -240
- data/nmatrix.gemspec +0 -55
- data/scripts/mac-brew-gcc.sh +0 -50
- data/scripts/mac-mavericks-brew-gcc.sh +0 -22
- data/spec/lapack_spec.rb +0 -459
data/ext/nmatrix/math/nrm2.h
CHANGED
@@ -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) {
|
data/ext/nmatrix/math/rot.h
CHANGED
@@ -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
|
data/ext/nmatrix/math/rotg.h
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
data/ext/nmatrix/math/scal.h
CHANGED
@@ -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
|
*/
|
data/ext/nmatrix/math/trsm.h
CHANGED
@@ -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
|
data/ext/nmatrix/nmatrix.cpp
CHANGED
@@ -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>
|
data/ext/nmatrix/nmatrix.h
CHANGED
@@ -43,14 +43,14 @@
|
|
43
43
|
#endif
|
44
44
|
|
45
45
|
#ifdef BENCHMARK
|
46
|
-
|
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
|
-
|
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
|
-
|
67
|
+
#error SIZEOF_INT undefined
|
68
68
|
#else
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
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
|
-
|
123
|
-
|
122
|
+
#define RETURN_SIZED_ENUMERATOR_PRE do { \
|
123
|
+
if (!rb_block_given_p()) {
|
124
124
|
|
125
125
|
//remaining portion
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
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
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
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
|
-
|
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
|
-
|
153
|
-
|
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
|
-
|
184
|
-
|
183
|
+
int count; \
|
184
|
+
NM_DECL_STRUCT(STORAGE*, src);
|
185
185
|
#define NM_DEF_STORAGE_CHILD_STRUCT_PRE(name) typedef struct NM_ ## name { \
|
186
|
-
|
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
|
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,
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
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
|
-
|
254
|
-
size_t*
|
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
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
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
|
-
|
279
|
-
|
280
|
-
|
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)
|
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
|
-
|
352
|
-
|
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
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
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
|
-
|
377
|
-
|
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
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
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
|
391
|
-
void nm_unregister_storage(NM_DECL_ENUM(stype_t, stype), const
|
392
|
-
void nm_register_nmatrix(
|
393
|
-
void nm_unregister_nmatrix(
|
394
|
-
void
|
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
|