nmatrix-atlas 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 (82) hide show
  1. checksums.yaml +7 -0
  2. data/ext/nmatrix/data/complex.h +364 -0
  3. data/ext/nmatrix/data/data.h +638 -0
  4. data/ext/nmatrix/data/meta.h +64 -0
  5. data/ext/nmatrix/data/ruby_object.h +389 -0
  6. data/ext/nmatrix/math/asum.h +120 -0
  7. data/ext/nmatrix/math/cblas_enums.h +36 -0
  8. data/ext/nmatrix/math/cblas_templates_core.h +507 -0
  9. data/ext/nmatrix/math/gemm.h +241 -0
  10. data/ext/nmatrix/math/gemv.h +178 -0
  11. data/ext/nmatrix/math/getrf.h +255 -0
  12. data/ext/nmatrix/math/getrs.h +121 -0
  13. data/ext/nmatrix/math/imax.h +79 -0
  14. data/ext/nmatrix/math/laswp.h +165 -0
  15. data/ext/nmatrix/math/long_dtype.h +49 -0
  16. data/ext/nmatrix/math/math.h +744 -0
  17. data/ext/nmatrix/math/nrm2.h +160 -0
  18. data/ext/nmatrix/math/rot.h +117 -0
  19. data/ext/nmatrix/math/rotg.h +106 -0
  20. data/ext/nmatrix/math/scal.h +71 -0
  21. data/ext/nmatrix/math/trsm.h +332 -0
  22. data/ext/nmatrix/math/util.h +148 -0
  23. data/ext/nmatrix/nm_memory.h +60 -0
  24. data/ext/nmatrix/nmatrix.h +408 -0
  25. data/ext/nmatrix/ruby_constants.h +106 -0
  26. data/ext/nmatrix/storage/common.h +176 -0
  27. data/ext/nmatrix/storage/dense/dense.h +128 -0
  28. data/ext/nmatrix/storage/list/list.h +137 -0
  29. data/ext/nmatrix/storage/storage.h +98 -0
  30. data/ext/nmatrix/storage/yale/class.h +1139 -0
  31. data/ext/nmatrix/storage/yale/iterators/base.h +142 -0
  32. data/ext/nmatrix/storage/yale/iterators/iterator.h +130 -0
  33. data/ext/nmatrix/storage/yale/iterators/row.h +449 -0
  34. data/ext/nmatrix/storage/yale/iterators/row_stored.h +139 -0
  35. data/ext/nmatrix/storage/yale/iterators/row_stored_nd.h +168 -0
  36. data/ext/nmatrix/storage/yale/iterators/stored_diagonal.h +123 -0
  37. data/ext/nmatrix/storage/yale/math/transpose.h +110 -0
  38. data/ext/nmatrix/storage/yale/yale.h +202 -0
  39. data/ext/nmatrix/types.h +54 -0
  40. data/ext/nmatrix/util/io.h +115 -0
  41. data/ext/nmatrix/util/sl_list.h +143 -0
  42. data/ext/nmatrix/util/util.h +78 -0
  43. data/ext/nmatrix_atlas/extconf.rb +250 -0
  44. data/ext/nmatrix_atlas/math_atlas.cpp +1206 -0
  45. data/ext/nmatrix_atlas/math_atlas/cblas_templates_atlas.h +72 -0
  46. data/ext/nmatrix_atlas/math_atlas/clapack_templates.h +332 -0
  47. data/ext/nmatrix_atlas/math_atlas/geev.h +82 -0
  48. data/ext/nmatrix_atlas/math_atlas/gesdd.h +83 -0
  49. data/ext/nmatrix_atlas/math_atlas/gesvd.h +81 -0
  50. data/ext/nmatrix_atlas/math_atlas/inc.h +47 -0
  51. data/ext/nmatrix_atlas/nmatrix_atlas.cpp +44 -0
  52. data/lib/nmatrix/atlas.rb +213 -0
  53. data/lib/nmatrix/lapack_ext_common.rb +69 -0
  54. data/spec/00_nmatrix_spec.rb +730 -0
  55. data/spec/01_enum_spec.rb +190 -0
  56. data/spec/02_slice_spec.rb +389 -0
  57. data/spec/03_nmatrix_monkeys_spec.rb +78 -0
  58. data/spec/2x2_dense_double.mat +0 -0
  59. data/spec/4x4_sparse.mat +0 -0
  60. data/spec/4x5_dense.mat +0 -0
  61. data/spec/blas_spec.rb +193 -0
  62. data/spec/elementwise_spec.rb +303 -0
  63. data/spec/homogeneous_spec.rb +99 -0
  64. data/spec/io/fortran_format_spec.rb +88 -0
  65. data/spec/io/harwell_boeing_spec.rb +98 -0
  66. data/spec/io/test.rua +9 -0
  67. data/spec/io_spec.rb +149 -0
  68. data/spec/lapack_core_spec.rb +482 -0
  69. data/spec/leakcheck.rb +16 -0
  70. data/spec/math_spec.rb +730 -0
  71. data/spec/nmatrix_yale_resize_test_associations.yaml +2802 -0
  72. data/spec/nmatrix_yale_spec.rb +286 -0
  73. data/spec/plugins/atlas/atlas_spec.rb +242 -0
  74. data/spec/rspec_monkeys.rb +56 -0
  75. data/spec/rspec_spec.rb +34 -0
  76. data/spec/shortcuts_spec.rb +310 -0
  77. data/spec/slice_set_spec.rb +157 -0
  78. data/spec/spec_helper.rb +140 -0
  79. data/spec/stat_spec.rb +203 -0
  80. data/spec/test.pcd +20 -0
  81. data/spec/utm5940.mtx +83844 -0
  82. metadata +159 -0
@@ -0,0 +1,332 @@
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
+ // == trsm.h
25
+ //
26
+ // trsm function in native C++.
27
+ //
28
+ /*
29
+ * Automatically Tuned Linear Algebra Software v3.8.4
30
+ * (C) Copyright 1999 R. Clint Whaley
31
+ *
32
+ * Redistribution and use in source and binary forms, with or without
33
+ * modification, are permitted provided that the following conditions
34
+ * are met:
35
+ * 1. Redistributions of source code must retain the above copyright
36
+ * notice, this list of conditions and the following disclaimer.
37
+ * 2. Redistributions in binary form must reproduce the above copyright
38
+ * notice, this list of conditions, and the following disclaimer in the
39
+ * documentation and/or other materials provided with the distribution.
40
+ * 3. The name of the ATLAS group or the names of its contributers may
41
+ * not be used to endorse or promote products derived from this
42
+ * software without specific written permission.
43
+ *
44
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
45
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
46
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
47
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ATLAS GROUP OR ITS CONTRIBUTORS
48
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
49
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
50
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
51
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
52
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
53
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
54
+ * POSSIBILITY OF SUCH DAMAGE.
55
+ *
56
+ */
57
+
58
+ #ifndef TRSM_H
59
+ #define TRSM_H
60
+
61
+
62
+ namespace nm { namespace math {
63
+
64
+
65
+ /*
66
+ * This version of trsm doesn't do any error checks and only works on column-major matrices.
67
+ *
68
+ * For row major, call trsm<DType> instead. That will handle necessary changes-of-variables
69
+ * and parameter checks.
70
+ *
71
+ * Note that some of the boundary conditions here may be incorrect. Very little has been tested!
72
+ * This was converted directly from dtrsm.f using f2c, and then rewritten more cleanly.
73
+ */
74
+ template <typename DType>
75
+ inline void trsm_nothrow(const enum CBLAS_SIDE side, const enum CBLAS_UPLO uplo,
76
+ const enum CBLAS_TRANSPOSE trans_a, const enum CBLAS_DIAG diag,
77
+ const int m, const int n, const DType alpha, const DType* a,
78
+ const int lda, DType* b, const int ldb)
79
+ {
80
+
81
+ // (row-major) trsm: left upper trans nonunit m=3 n=1 1/1 a 3 b 3
82
+
83
+ if (m == 0 || n == 0) return; /* Quick return if possible. */
84
+
85
+ if (alpha == 0) { // Handle alpha == 0
86
+ for (int j = 0; j < n; ++j) {
87
+ for (int i = 0; i < m; ++i) {
88
+ b[i + j * ldb] = 0;
89
+ }
90
+ }
91
+ return;
92
+ }
93
+
94
+ if (side == CblasLeft) {
95
+ if (trans_a == CblasNoTrans) {
96
+
97
+ /* Form B := alpha*inv( A )*B. */
98
+ if (uplo == CblasUpper) {
99
+ for (int j = 0; j < n; ++j) {
100
+ if (alpha != 1) {
101
+ for (int i = 0; i < m; ++i) {
102
+ b[i + j * ldb] = alpha * b[i + j * ldb];
103
+ }
104
+ }
105
+ for (int k = m-1; k >= 0; --k) {
106
+ if (b[k + j * ldb] != 0) {
107
+ if (diag == CblasNonUnit) {
108
+ b[k + j * ldb] /= a[k + k * lda];
109
+ }
110
+
111
+ for (int i = 0; i < k-1; ++i) {
112
+ b[i + j * ldb] -= b[k + j * ldb] * a[i + k * lda];
113
+ }
114
+ }
115
+ }
116
+ }
117
+ } else {
118
+ for (int j = 0; j < n; ++j) {
119
+ if (alpha != 1) {
120
+ for (int i = 0; i < m; ++i) {
121
+ b[i + j * ldb] = alpha * b[i + j * ldb];
122
+ }
123
+ }
124
+ for (int k = 0; k < m; ++k) {
125
+ if (b[k + j * ldb] != 0.) {
126
+ if (diag == CblasNonUnit) {
127
+ b[k + j * ldb] /= a[k + k * lda];
128
+ }
129
+ for (int i = k+1; i < m; ++i) {
130
+ b[i + j * ldb] -= b[k + j * ldb] * a[i + k * lda];
131
+ }
132
+ }
133
+ }
134
+ }
135
+ }
136
+ } else { // CblasTrans
137
+
138
+ /* Form B := alpha*inv( A**T )*B. */
139
+ if (uplo == CblasUpper) {
140
+ for (int j = 0; j < n; ++j) {
141
+ for (int i = 0; i < m; ++i) {
142
+ DType temp = alpha * b[i + j * ldb];
143
+ for (int k = 0; k < i; ++k) { // limit was i-1. Lots of similar bugs in this code, probably.
144
+ temp -= a[k + i * lda] * b[k + j * ldb];
145
+ }
146
+ if (diag == CblasNonUnit) {
147
+ temp /= a[i + i * lda];
148
+ }
149
+ b[i + j * ldb] = temp;
150
+ }
151
+ }
152
+ } else {
153
+ for (int j = 0; j < n; ++j) {
154
+ for (int i = m-1; i >= 0; --i) {
155
+ DType temp= alpha * b[i + j * ldb];
156
+ for (int k = i+1; k < m; ++k) {
157
+ temp -= a[k + i * lda] * b[k + j * ldb];
158
+ }
159
+ if (diag == CblasNonUnit) {
160
+ temp /= a[i + i * lda];
161
+ }
162
+ b[i + j * ldb] = temp;
163
+ }
164
+ }
165
+ }
166
+ }
167
+ } else { // right side
168
+
169
+ if (trans_a == CblasNoTrans) {
170
+
171
+ /* Form B := alpha*B*inv( A ). */
172
+
173
+ if (uplo == CblasUpper) {
174
+ for (int j = 0; j < n; ++j) {
175
+ if (alpha != 1) {
176
+ for (int i = 0; i < m; ++i) {
177
+ b[i + j * ldb] = alpha * b[i + j * ldb];
178
+ }
179
+ }
180
+ for (int k = 0; k < j-1; ++k) {
181
+ if (a[k + j * lda] != 0) {
182
+ for (int i = 0; i < m; ++i) {
183
+ b[i + j * ldb] -= a[k + j * lda] * b[i + k * ldb];
184
+ }
185
+ }
186
+ }
187
+ if (diag == CblasNonUnit) {
188
+ DType temp = 1 / a[j + j * lda];
189
+ for (int i = 0; i < m; ++i) {
190
+ b[i + j * ldb] = temp * b[i + j * ldb];
191
+ }
192
+ }
193
+ }
194
+ } else {
195
+ for (int j = n-1; j >= 0; --j) {
196
+ if (alpha != 1) {
197
+ for (int i = 0; i < m; ++i) {
198
+ b[i + j * ldb] = alpha * b[i + j * ldb];
199
+ }
200
+ }
201
+
202
+ for (int k = j+1; k < n; ++k) {
203
+ if (a[k + j * lda] != 0.) {
204
+ for (int i = 0; i < m; ++i) {
205
+ b[i + j * ldb] -= a[k + j * lda] * b[i + k * ldb];
206
+ }
207
+ }
208
+ }
209
+ if (diag == CblasNonUnit) {
210
+ DType temp = 1 / a[j + j * lda];
211
+
212
+ for (int i = 0; i < m; ++i) {
213
+ b[i + j * ldb] = temp * b[i + j * ldb];
214
+ }
215
+ }
216
+ }
217
+ }
218
+ } else { // CblasTrans
219
+
220
+ /* Form B := alpha*B*inv( A**T ). */
221
+
222
+ if (uplo == CblasUpper) {
223
+ for (int k = n-1; k >= 0; --k) {
224
+ if (diag == CblasNonUnit) {
225
+ DType temp= 1 / a[k + k * lda];
226
+ for (int i = 0; i < m; ++i) {
227
+ b[i + k * ldb] = temp * b[i + k * ldb];
228
+ }
229
+ }
230
+ for (int j = 0; j < k-1; ++j) {
231
+ if (a[j + k * lda] != 0.) {
232
+ DType temp= a[j + k * lda];
233
+ for (int i = 0; i < m; ++i) {
234
+ b[i + j * ldb] -= temp * b[i + k * ldb];
235
+ }
236
+ }
237
+ }
238
+ if (alpha != 1) {
239
+ for (int i = 0; i < m; ++i) {
240
+ b[i + k * ldb] = alpha * b[i + k * ldb];
241
+ }
242
+ }
243
+ }
244
+ } else {
245
+ for (int k = 0; k < n; ++k) {
246
+ if (diag == CblasNonUnit) {
247
+ DType temp = 1 / a[k + k * lda];
248
+ for (int i = 0; i < m; ++i) {
249
+ b[i + k * ldb] = temp * b[i + k * ldb];
250
+ }
251
+ }
252
+ for (int j = k+1; j < n; ++j) {
253
+ if (a[j + k * lda] != 0.) {
254
+ DType temp = a[j + k * lda];
255
+ for (int i = 0; i < m; ++i) {
256
+ b[i + j * ldb] -= temp * b[i + k * ldb];
257
+ }
258
+ }
259
+ }
260
+ if (alpha != 1) {
261
+ for (int i = 0; i < m; ++i) {
262
+ b[i + k * ldb] = alpha * b[i + k * ldb];
263
+ }
264
+ }
265
+ }
266
+ }
267
+ }
268
+ }
269
+ }
270
+
271
+ /*
272
+ * BLAS' DTRSM function, generalized.
273
+ */
274
+ template <typename DType, typename = typename std::enable_if<!std::is_integral<DType>::value>::type>
275
+ inline void trsm(const enum CBLAS_ORDER order,
276
+ const enum CBLAS_SIDE side, const enum CBLAS_UPLO uplo,
277
+ const enum CBLAS_TRANSPOSE trans_a, const enum CBLAS_DIAG diag,
278
+ const int m, const int n, const DType alpha, const DType* a,
279
+ const int lda, DType* b, const int ldb)
280
+ {
281
+ /*using std::cerr;
282
+ using std::endl;*/
283
+
284
+ int num_rows_a = n;
285
+ if (side == CblasLeft) num_rows_a = m;
286
+
287
+ if (lda < std::max(1,num_rows_a)) {
288
+ fprintf(stderr, "TRSM: num_rows_a = %d; got lda=%d\n", num_rows_a, lda);
289
+ rb_raise(rb_eArgError, "TRSM: Expected lda >= max(1, num_rows_a)");
290
+ }
291
+
292
+ // Test the input parameters.
293
+ if (order == CblasRowMajor) {
294
+ if (ldb < std::max(1,n)) {
295
+ fprintf(stderr, "TRSM: M=%d; got ldb=%d\n", m, ldb);
296
+ rb_raise(rb_eArgError, "TRSM: Expected ldb >= max(1,N)");
297
+ }
298
+
299
+ // For row major, need to switch side and uplo
300
+ enum CBLAS_SIDE side_ = side == CblasLeft ? CblasRight : CblasLeft;
301
+ enum CBLAS_UPLO uplo_ = uplo == CblasUpper ? CblasLower : CblasUpper;
302
+
303
+ /*
304
+ cerr << "(row-major) trsm: " << (side_ == CblasLeft ? "left " : "right ")
305
+ << (uplo_ == CblasUpper ? "upper " : "lower ")
306
+ << (trans_a == CblasTrans ? "trans " : "notrans ")
307
+ << (diag == CblasNonUnit ? "nonunit " : "unit ")
308
+ << n << " " << m << " " << alpha << " a " << lda << " b " << ldb << endl;
309
+ */
310
+ trsm_nothrow<DType>(side_, uplo_, trans_a, diag, n, m, alpha, a, lda, b, ldb);
311
+
312
+ } else { // CblasColMajor
313
+
314
+ if (ldb < std::max(1,m)) {
315
+ fprintf(stderr, "TRSM: M=%d; got ldb=%d\n", m, ldb);
316
+ rb_raise(rb_eArgError, "TRSM: Expected ldb >= max(1,M)");
317
+ }
318
+ /*
319
+ cerr << "(col-major) trsm: " << (side == CblasLeft ? "left " : "right ")
320
+ << (uplo == CblasUpper ? "upper " : "lower ")
321
+ << (trans_a == CblasTrans ? "trans " : "notrans ")
322
+ << (diag == CblasNonUnit ? "nonunit " : "unit ")
323
+ << m << " " << n << " " << alpha << " a " << lda << " b " << ldb << endl;
324
+ */
325
+ trsm_nothrow<DType>(side, uplo, trans_a, diag, m, n, alpha, a, lda, b, ldb);
326
+
327
+ }
328
+
329
+ }
330
+
331
+ } } // namespace nm::math
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