nmatrix 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. data/.gitignore +27 -0
  2. data/.rspec +2 -0
  3. data/Gemfile +3 -5
  4. data/Guardfile +6 -0
  5. data/History.txt +33 -0
  6. data/Manifest.txt +41 -38
  7. data/README.rdoc +88 -11
  8. data/Rakefile +35 -53
  9. data/ext/nmatrix/data/complex.h +372 -0
  10. data/ext/nmatrix/data/data.cpp +275 -0
  11. data/ext/nmatrix/data/data.h +707 -0
  12. data/ext/nmatrix/data/rational.h +421 -0
  13. data/ext/nmatrix/data/ruby_object.h +446 -0
  14. data/ext/nmatrix/extconf.rb +101 -51
  15. data/ext/nmatrix/new_extconf.rb +56 -0
  16. data/ext/nmatrix/nmatrix.cpp +1609 -0
  17. data/ext/nmatrix/nmatrix.h +265 -849
  18. data/ext/nmatrix/ruby_constants.cpp +134 -0
  19. data/ext/nmatrix/ruby_constants.h +103 -0
  20. data/ext/nmatrix/storage/common.cpp +70 -0
  21. data/ext/nmatrix/storage/common.h +170 -0
  22. data/ext/nmatrix/storage/dense.cpp +665 -0
  23. data/ext/nmatrix/storage/dense.h +116 -0
  24. data/ext/nmatrix/storage/list.cpp +1088 -0
  25. data/ext/nmatrix/storage/list.h +129 -0
  26. data/ext/nmatrix/storage/storage.cpp +658 -0
  27. data/ext/nmatrix/storage/storage.h +99 -0
  28. data/ext/nmatrix/storage/yale.cpp +1601 -0
  29. data/ext/nmatrix/storage/yale.h +208 -0
  30. data/ext/nmatrix/ttable_helper.rb +126 -0
  31. data/ext/nmatrix/{yale/smmp1_header.template.c → types.h} +36 -9
  32. data/ext/nmatrix/util/io.cpp +295 -0
  33. data/ext/nmatrix/util/io.h +117 -0
  34. data/ext/nmatrix/util/lapack.h +1175 -0
  35. data/ext/nmatrix/util/math.cpp +557 -0
  36. data/ext/nmatrix/util/math.h +1363 -0
  37. data/ext/nmatrix/util/sl_list.cpp +475 -0
  38. data/ext/nmatrix/util/sl_list.h +255 -0
  39. data/ext/nmatrix/util/util.h +78 -0
  40. data/lib/nmatrix/blas.rb +70 -0
  41. data/lib/nmatrix/io/mat5_reader.rb +567 -0
  42. data/lib/nmatrix/io/mat_reader.rb +162 -0
  43. data/lib/{string.rb → nmatrix/monkeys.rb} +49 -2
  44. data/lib/nmatrix/nmatrix.rb +199 -0
  45. data/lib/nmatrix/nvector.rb +103 -0
  46. data/lib/nmatrix/version.rb +27 -0
  47. data/lib/nmatrix.rb +22 -230
  48. data/nmatrix.gemspec +59 -0
  49. data/scripts/mac-brew-gcc.sh +47 -0
  50. data/spec/4x4_sparse.mat +0 -0
  51. data/spec/4x5_dense.mat +0 -0
  52. data/spec/blas_spec.rb +47 -0
  53. data/spec/elementwise_spec.rb +164 -0
  54. data/spec/io_spec.rb +60 -0
  55. data/spec/lapack_spec.rb +52 -0
  56. data/spec/math_spec.rb +96 -0
  57. data/spec/nmatrix_spec.rb +93 -89
  58. data/spec/nmatrix_yale_spec.rb +52 -36
  59. data/spec/nvector_spec.rb +1 -1
  60. data/spec/slice_spec.rb +257 -0
  61. data/spec/spec_helper.rb +51 -0
  62. data/spec/utm5940.mtx +83844 -0
  63. metadata +113 -71
  64. data/.autotest +0 -23
  65. data/.gemtest +0 -0
  66. data/ext/nmatrix/cblas.c +0 -150
  67. data/ext/nmatrix/dense/blas_header.template.c +0 -52
  68. data/ext/nmatrix/dense/elementwise.template.c +0 -107
  69. data/ext/nmatrix/dense/gemm.template.c +0 -159
  70. data/ext/nmatrix/dense/gemv.template.c +0 -130
  71. data/ext/nmatrix/dense/rationalmath.template.c +0 -68
  72. data/ext/nmatrix/dense.c +0 -307
  73. data/ext/nmatrix/depend +0 -18
  74. data/ext/nmatrix/generator/syntax_tree.rb +0 -481
  75. data/ext/nmatrix/generator.rb +0 -594
  76. data/ext/nmatrix/list.c +0 -774
  77. data/ext/nmatrix/nmatrix.c +0 -1977
  78. data/ext/nmatrix/rational.c +0 -98
  79. data/ext/nmatrix/yale/complexmath.template.c +0 -71
  80. data/ext/nmatrix/yale/elementwise.template.c +0 -46
  81. data/ext/nmatrix/yale/elementwise_op.template.c +0 -73
  82. data/ext/nmatrix/yale/numbmm.template.c +0 -94
  83. data/ext/nmatrix/yale/smmp1.template.c +0 -21
  84. data/ext/nmatrix/yale/smmp2.template.c +0 -43
  85. data/ext/nmatrix/yale/smmp2_header.template.c +0 -46
  86. data/ext/nmatrix/yale/sort_columns.template.c +0 -56
  87. data/ext/nmatrix/yale/symbmm.template.c +0 -54
  88. data/ext/nmatrix/yale/transp.template.c +0 -68
  89. data/ext/nmatrix/yale.c +0 -726
  90. data/lib/array.rb +0 -67
  91. data/spec/syntax_tree_spec.rb +0 -46
@@ -0,0 +1,255 @@
1
+ /////////////////////////////////////////////////////////////////////
2
+ // = NMatrix
3
+ //
4
+ // A linear algebra library for scientific computation in Ruby.
5
+ // NMatrix is part of SciRuby.
6
+ //
7
+ // NMatrix was originally inspired by and derived from NArray, by
8
+ // Masahiro Tanaka: http://narray.rubyforge.org
9
+ //
10
+ // == Copyright Information
11
+ //
12
+ // SciRuby is Copyright (c) 2010 - 2012, Ruby Science Foundation
13
+ // NMatrix is Copyright (c) 2012, Ruby Science Foundation
14
+ //
15
+ // Please see LICENSE.txt for additional copyright notices.
16
+ //
17
+ // == Contributing
18
+ //
19
+ // By contributing source code to SciRuby, you agree to be bound by
20
+ // our Contributor Agreement:
21
+ //
22
+ // * https://github.com/SciRuby/sciruby/wiki/Contributor-Agreement
23
+ //
24
+ // == sl_list.h
25
+ //
26
+ // Singly-linked list implementation used for List Storage.
27
+
28
+ #ifndef SL_LIST_H
29
+ #define SL_LIST_H
30
+
31
+
32
+ /*
33
+ * Standard Includes
34
+ */
35
+
36
+ #include <type_traits>
37
+ #include <cstdlib>
38
+
39
+ /*
40
+ * Project Includes
41
+ */
42
+
43
+ #include "types.h"
44
+
45
+ #include "data/data.h"
46
+
47
+ #include "nmatrix.h"
48
+
49
+ namespace nm { namespace list {
50
+
51
+ /*
52
+ * Macros
53
+ */
54
+
55
+ /*
56
+ * Types
57
+ */
58
+
59
+ /*
60
+ * Data
61
+ */
62
+
63
+
64
+ /*
65
+ * Functions
66
+ */
67
+
68
+ ////////////////
69
+ // Lifecycle //
70
+ ///////////////
71
+
72
+ LIST* create(void);
73
+ void del(LIST* list, size_t recursions);
74
+ void mark(LIST* list, size_t recursions);
75
+
76
+ ///////////////
77
+ // Accessors //
78
+ ///////////////
79
+
80
+ NODE* insert(LIST* list, bool replace, size_t key, void* val);
81
+ NODE* insert_with_copy(LIST *list, size_t key, void *val, size_t size);
82
+ NODE* insert_after(NODE* node, size_t key, void* val);
83
+ void* remove(LIST* list, size_t key);
84
+ bool remove_recursive(LIST* list, const size_t* coords, const size_t* offset, size_t r, const size_t& dim, void* rm);
85
+
86
+ template <typename Type>
87
+ inline NODE* insert_helper(LIST* list, NODE* node, size_t key, Type val) {
88
+ Type* val_mem = ALLOC(Type);
89
+ *val_mem = val;
90
+
91
+ if (node == NULL) {
92
+ return insert(list, false, key, val_mem);
93
+
94
+ } else {
95
+ return insert_after(node, key, val_mem);
96
+ }
97
+ }
98
+
99
+ template <typename Type>
100
+ inline NODE* insert_helper(LIST* list, NODE* node, size_t key, Type* ptr) {
101
+ if (node == NULL) {
102
+ return insert(list, false, key, ptr);
103
+
104
+ } else {
105
+ return insert_after(node, key, ptr);
106
+ }
107
+ }
108
+
109
+ ///////////
110
+ // Tests //
111
+ ///////////
112
+
113
+ /*
114
+ * Do all values in a list == some value?
115
+ *
116
+ * Note that the template parameters should line up with the first two function parameters. This differs from most
117
+ * other eqeq functions, which use left and right dtypes.
118
+ */
119
+ template <typename ListDType, typename ValueDType>
120
+ bool eqeq_value(const LIST* l, const ValueDType* v, size_t recursions, size_t& checked) {
121
+ NODE *next, *curr = l->first;
122
+
123
+ while (curr) {
124
+ next = curr->next;
125
+
126
+ if (recursions == 0) {
127
+ ++checked;
128
+
129
+ if (*reinterpret_cast<ListDType*>(curr->val) != *v) return false;
130
+
131
+ } else if (!eqeq_value<ListDType,ValueDType>((LIST*)curr->val, v, recursions - 1, checked)) {
132
+ return false;
133
+ }
134
+
135
+ curr = next;
136
+ }
137
+
138
+ return true;
139
+ }
140
+
141
+
142
+ /*
143
+ * Are all values in the two lists equal? If one is missing a value, but the
144
+ * other isn't, does the value in the list match the default value?
145
+ */
146
+ template <typename LDType, typename RDType>
147
+ bool eqeq(const LIST* left, const LIST* right, const LDType* left_val, const RDType* right_val, size_t recursions, size_t& checked) {
148
+ NODE *lnext = NULL, *lcurr = left->first, *rnext = NULL, *rcurr = right->first;
149
+
150
+ if (lcurr) lnext = lcurr->next;
151
+ if (rcurr) rnext = rcurr->next;
152
+
153
+ while (lcurr && rcurr) {
154
+
155
+ if (lcurr->key == rcurr->key) {
156
+ // MATCHING KEYS
157
+
158
+ if (recursions == 0) {
159
+ ++checked;
160
+
161
+ if (*reinterpret_cast<LDType*>(lcurr->val) != *reinterpret_cast<RDType*>(rcurr->val)) return false;
162
+
163
+ } else if (!eqeq<LDType,RDType>(reinterpret_cast<LIST*>(lcurr->val), (LIST*)rcurr->val, left_val, right_val, recursions - 1, checked)) {
164
+ return false;
165
+ }
166
+
167
+ // increment both iterators
168
+ rcurr = rnext;
169
+ if (rcurr) rnext = rcurr->next;
170
+ lcurr = lnext;
171
+ if (lcurr) lnext = lcurr->next;
172
+
173
+ } else if (lcurr->key < rcurr->key) {
174
+ // NON-MATCHING KEYS
175
+
176
+ if (recursions == 0) {
177
+ // compare left entry to right default value
178
+ ++checked;
179
+
180
+ if (*reinterpret_cast<LDType*>(lcurr->val) != *right_val) return false;
181
+
182
+ } else if (!eqeq_value<LDType,RDType>(reinterpret_cast<LIST*>(lcurr->val), right_val, recursions - 1, checked)) {
183
+ return false;
184
+ }
185
+
186
+ // increment left iterator
187
+ lcurr = lnext;
188
+ if (lcurr) lnext = lcurr->next;
189
+
190
+ } else {
191
+ // if (rcurr->key < lcurr->key)
192
+
193
+ if (recursions == 0) {
194
+ // compare right entry to left default value
195
+ ++checked;
196
+
197
+ if (*reinterpret_cast<RDType*>(rcurr->val) != *left_val) return false;
198
+
199
+ } else if (!eqeq_value<RDType,LDType>(reinterpret_cast<LIST*>(rcurr->val), left_val, recursions - 1, checked)) {
200
+ return false;
201
+ }
202
+
203
+ // increment right iterator
204
+ rcurr = rnext;
205
+ if (rcurr) rnext = rcurr->next;
206
+ }
207
+
208
+ }
209
+
210
+ /*
211
+ * One final check, in case we get to the end of one list but not the other
212
+ * one.
213
+ */
214
+ if (lcurr) {
215
+ // nothing left in right-hand list
216
+ if (*reinterpret_cast<LDType*>(lcurr->val) != *right_val) return false;
217
+
218
+ } else if (rcurr) {
219
+ // nothing left in left-hand list
220
+ if (*reinterpret_cast<RDType*>(rcurr->val) != *left_val) return false;
221
+
222
+ }
223
+
224
+ /*
225
+ * Nothing different between the two lists -- but make sure after this return
226
+ * that you compare the default values themselves, if we haven't visited
227
+ * every value in the two matrices.
228
+ */
229
+ return true;
230
+ }
231
+
232
+ /////////////
233
+ // Utility //
234
+ /////////////
235
+
236
+ NODE* find(LIST* list, size_t key);
237
+ NODE* find_preceding_from(NODE* prev, size_t key);
238
+ NODE* find_nearest(LIST* list, size_t key);
239
+ NODE* find_nearest_from(NODE* prev, size_t key);
240
+
241
+ /////////////////////////
242
+ // Copying and Casting //
243
+ /////////////////////////
244
+
245
+ template <typename LDType, typename RDType>
246
+ void cast_copy_contents(LIST* lhs, const LIST* rhs, size_t recursions);
247
+
248
+ }} // end of namespace nm::list
249
+
250
+ extern "C" {
251
+ void nm_list_cast_copy_contents(LIST* lhs, const LIST* rhs, dtype_t lhs_dtype, dtype_t rhs_dtype, size_t recursions);
252
+ VALUE nm_list_copy_to_hash(const LIST* l, const dtype_t dtype, size_t recursions, VALUE default_value);
253
+ } // end of extern "C" block
254
+
255
+ #endif // SL_LIST_H
@@ -0,0 +1,78 @@
1
+ /////////////////////////////////////////////////////////////////////
2
+ // = NMatrix
3
+ //
4
+ // A linear algebra library for scientific computation in Ruby.
5
+ // NMatrix is part of SciRuby.
6
+ //
7
+ // NMatrix was originally inspired by and derived from NArray, by
8
+ // Masahiro Tanaka: http://narray.rubyforge.org
9
+ //
10
+ // == Copyright Information
11
+ //
12
+ // SciRuby is Copyright (c) 2010 - 2012, Ruby Science Foundation
13
+ // NMatrix is Copyright (c) 2012, Ruby Science Foundation
14
+ //
15
+ // Please see LICENSE.txt for additional copyright notices.
16
+ //
17
+ // == Contributing
18
+ //
19
+ // By contributing source code to SciRuby, you agree to be bound by
20
+ // our Contributor Agreement:
21
+ //
22
+ // * https://github.com/SciRuby/sciruby/wiki/Contributor-Agreement
23
+ //
24
+ // == util.h
25
+ //
26
+ // Header file for utility functions and data.
27
+
28
+ #ifndef UTIL_H
29
+ #define UTIL_H
30
+
31
+ /*
32
+ * Standard Includes
33
+ */
34
+
35
+ /*
36
+ * Project Includes
37
+ */
38
+
39
+ #include "types.h"
40
+
41
+ /*
42
+ * Macros
43
+ */
44
+
45
+ /*
46
+ * Types
47
+ */
48
+
49
+ /*
50
+ * Data
51
+ */
52
+
53
+ /*
54
+ * Functions
55
+ */
56
+ namespace nm {
57
+ template <typename Type>
58
+ inline Type gcf(Type x, Type y) {
59
+ Type t;
60
+
61
+ if (x < 0) x = -x;
62
+ if (y < 0) y = -y;
63
+
64
+ if (x == 0) return y;
65
+ if (y == 0) return x;
66
+
67
+ while (x > 0) {
68
+ t = x;
69
+ x = y % x;
70
+ y = t;
71
+ }
72
+
73
+ return y;
74
+ }
75
+ } // end of namespace nm
76
+
77
+
78
+ #endif // UTIL_H
@@ -0,0 +1,70 @@
1
+ module NMatrix::BLAS
2
+
3
+ class << self
4
+
5
+ def gemm(a, b, c = nil, alpha = 1.0, beta = 0.0, transpose_a = false, transpose_b = false, m = nil, n = nil, k = nil, lda = nil, ldb = nil, ldc = nil)
6
+ raise ArgumentError, 'Expected dense NMatrices as first two arguments.' unless a.is_a?(NMatrix) and b.is_a?(NMatrix) and a.stype == :dense and b.stype == :dense
7
+ raise ArgumentError, 'Expected nil or dense NMatrix as third argument.' unless c.nil? or (c.is_a?(NMatrix) and c.stype == :dense)
8
+ raise ArgumentError, 'NMatrix dtype mismatch.' unless a.dtype == b.dtype and (c ? a.dtype == c.dtype : true)
9
+
10
+ # First, set m, n, and k, which depend on whether we're taking the
11
+ # transpose of a and b.
12
+ if c
13
+ m ||= c.shape[0]
14
+ n ||= c.shape[1]
15
+ k ||= transpose_a ? a.shape[0] : a.shape[1]
16
+
17
+ else
18
+ if transpose_a
19
+ # Either :transpose or :complex_conjugate.
20
+ m ||= a.shape[1]
21
+ k ||= a.shape[0]
22
+
23
+ else
24
+ # No transpose.
25
+ m ||= a.shape[0]
26
+ k ||= a.shape[1]
27
+ end
28
+
29
+ n ||= transpose_b ? b.shape[0] : b.shape[1]
30
+ c = NMatrix.new([m, n], a.dtype)
31
+ end
32
+
33
+ # I think these are independent of whether or not a transpose occurs.
34
+ lda ||= a.shape[1]
35
+ ldb ||= b.shape[1]
36
+ ldc ||= c.shape[1]
37
+
38
+ # NM_COMPLEX64 and NM_COMPLEX128 both require complex alpha and beta.
39
+ if a.dtype == :complex64 or a.dtype == :complex128
40
+ alpha = Complex.new(1.0, 0.0) if alpha == 1.0
41
+ beta = Complex.new(0.0, 0.0) if beta == 0.0
42
+ end
43
+
44
+ # For argument descriptions, see: http://www.netlib.org/blas/dgemm.f
45
+ ::NMatrix::BLAS.cblas_gemm(:row, transpose_a, transpose_b, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc)
46
+
47
+ return c
48
+ end
49
+
50
+ def gemv(a, x, y = nil, alpha = 1.0, beta = 0.0, transpose_a = false, m = nil, n = nil, lda = nil, incx = nil, incy = nil)
51
+ m ||= transpose_a ? a.shape[1] : a.shape[0]
52
+ n ||= transpose_a ? a.shape[0] : a.shape[1]
53
+
54
+ lda ||= a.shape[1]
55
+ incx ||= 1
56
+ incy ||= 1
57
+
58
+ # NM_COMPLEX64 and NM_COMPLEX128 both require complex alpha and beta.
59
+ if a.dtype == :complex64 or a.dtype == :complex128
60
+ alpha = Complex.new(1.0, 0.0) if alpha == 1.0
61
+ beta = Complex.new(0.0, 0.0) if beta == 0.0
62
+ end
63
+
64
+ ::NMatrix::BLAS.cblas_gemv(transpose_a, m, n, alpha, a, lda, x, incx, beta, y, incy)
65
+
66
+ return y
67
+ end
68
+
69
+ end
70
+ end