nmatrix 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|