pnmatrix 1.2.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/ext/nmatrix/binary_format.txt +53 -0
- data/ext/nmatrix/data/complex.h +388 -0
- data/ext/nmatrix/data/data.cpp +274 -0
- data/ext/nmatrix/data/data.h +651 -0
- data/ext/nmatrix/data/meta.h +64 -0
- data/ext/nmatrix/data/ruby_object.h +386 -0
- data/ext/nmatrix/extconf.rb +70 -0
- data/ext/nmatrix/math/asum.h +99 -0
- data/ext/nmatrix/math/cblas_enums.h +36 -0
- data/ext/nmatrix/math/cblas_templates_core.h +507 -0
- data/ext/nmatrix/math/gemm.h +241 -0
- data/ext/nmatrix/math/gemv.h +178 -0
- data/ext/nmatrix/math/getrf.h +255 -0
- data/ext/nmatrix/math/getrs.h +121 -0
- data/ext/nmatrix/math/imax.h +82 -0
- data/ext/nmatrix/math/laswp.h +165 -0
- data/ext/nmatrix/math/long_dtype.h +62 -0
- data/ext/nmatrix/math/magnitude.h +54 -0
- data/ext/nmatrix/math/math.h +751 -0
- data/ext/nmatrix/math/nrm2.h +165 -0
- data/ext/nmatrix/math/rot.h +117 -0
- data/ext/nmatrix/math/rotg.h +106 -0
- data/ext/nmatrix/math/scal.h +71 -0
- data/ext/nmatrix/math/trsm.h +336 -0
- data/ext/nmatrix/math/util.h +162 -0
- data/ext/nmatrix/math.cpp +1368 -0
- data/ext/nmatrix/nm_memory.h +60 -0
- data/ext/nmatrix/nmatrix.cpp +285 -0
- data/ext/nmatrix/nmatrix.h +476 -0
- data/ext/nmatrix/ruby_constants.cpp +151 -0
- data/ext/nmatrix/ruby_constants.h +106 -0
- data/ext/nmatrix/ruby_nmatrix.c +3130 -0
- data/ext/nmatrix/storage/common.cpp +77 -0
- data/ext/nmatrix/storage/common.h +183 -0
- data/ext/nmatrix/storage/dense/dense.cpp +1096 -0
- data/ext/nmatrix/storage/dense/dense.h +129 -0
- data/ext/nmatrix/storage/list/list.cpp +1628 -0
- data/ext/nmatrix/storage/list/list.h +138 -0
- data/ext/nmatrix/storage/storage.cpp +730 -0
- data/ext/nmatrix/storage/storage.h +99 -0
- data/ext/nmatrix/storage/yale/class.h +1139 -0
- data/ext/nmatrix/storage/yale/iterators/base.h +143 -0
- data/ext/nmatrix/storage/yale/iterators/iterator.h +131 -0
- data/ext/nmatrix/storage/yale/iterators/row.h +450 -0
- data/ext/nmatrix/storage/yale/iterators/row_stored.h +140 -0
- data/ext/nmatrix/storage/yale/iterators/row_stored_nd.h +169 -0
- data/ext/nmatrix/storage/yale/iterators/stored_diagonal.h +124 -0
- data/ext/nmatrix/storage/yale/math/transpose.h +110 -0
- data/ext/nmatrix/storage/yale/yale.cpp +2074 -0
- data/ext/nmatrix/storage/yale/yale.h +203 -0
- data/ext/nmatrix/types.h +55 -0
- data/ext/nmatrix/util/io.cpp +279 -0
- data/ext/nmatrix/util/io.h +115 -0
- data/ext/nmatrix/util/sl_list.cpp +627 -0
- data/ext/nmatrix/util/sl_list.h +144 -0
- data/ext/nmatrix/util/util.h +78 -0
- data/lib/nmatrix/blas.rb +378 -0
- data/lib/nmatrix/cruby/math.rb +744 -0
- data/lib/nmatrix/enumerate.rb +253 -0
- data/lib/nmatrix/homogeneous.rb +241 -0
- data/lib/nmatrix/io/fortran_format.rb +138 -0
- data/lib/nmatrix/io/harwell_boeing.rb +221 -0
- data/lib/nmatrix/io/market.rb +263 -0
- data/lib/nmatrix/io/point_cloud.rb +189 -0
- data/lib/nmatrix/jruby/decomposition.rb +24 -0
- data/lib/nmatrix/jruby/enumerable.rb +13 -0
- data/lib/nmatrix/jruby/error.rb +4 -0
- data/lib/nmatrix/jruby/math.rb +501 -0
- data/lib/nmatrix/jruby/nmatrix_java.rb +840 -0
- data/lib/nmatrix/jruby/operators.rb +283 -0
- data/lib/nmatrix/jruby/slice.rb +264 -0
- data/lib/nmatrix/lapack_core.rb +181 -0
- data/lib/nmatrix/lapack_plugin.rb +44 -0
- data/lib/nmatrix/math.rb +953 -0
- data/lib/nmatrix/mkmf.rb +100 -0
- data/lib/nmatrix/monkeys.rb +137 -0
- data/lib/nmatrix/nmatrix.rb +1172 -0
- data/lib/nmatrix/rspec.rb +75 -0
- data/lib/nmatrix/shortcuts.rb +1163 -0
- data/lib/nmatrix/version.rb +39 -0
- data/lib/nmatrix/yale_functions.rb +118 -0
- data/lib/nmatrix.rb +28 -0
- data/spec/00_nmatrix_spec.rb +892 -0
- data/spec/01_enum_spec.rb +196 -0
- data/spec/02_slice_spec.rb +407 -0
- data/spec/03_nmatrix_monkeys_spec.rb +80 -0
- data/spec/2x2_dense_double.mat +0 -0
- data/spec/4x4_sparse.mat +0 -0
- data/spec/4x5_dense.mat +0 -0
- data/spec/blas_spec.rb +215 -0
- data/spec/elementwise_spec.rb +311 -0
- data/spec/homogeneous_spec.rb +100 -0
- data/spec/io/fortran_format_spec.rb +88 -0
- data/spec/io/harwell_boeing_spec.rb +98 -0
- data/spec/io/test.rua +9 -0
- data/spec/io_spec.rb +159 -0
- data/spec/lapack_core_spec.rb +482 -0
- data/spec/leakcheck.rb +16 -0
- data/spec/math_spec.rb +1363 -0
- data/spec/nmatrix_yale_resize_test_associations.yaml +2802 -0
- data/spec/nmatrix_yale_spec.rb +286 -0
- data/spec/rspec_monkeys.rb +56 -0
- data/spec/rspec_spec.rb +35 -0
- data/spec/shortcuts_spec.rb +474 -0
- data/spec/slice_set_spec.rb +162 -0
- data/spec/spec_helper.rb +172 -0
- data/spec/stat_spec.rb +214 -0
- data/spec/test.pcd +20 -0
- data/spec/utm5940.mtx +83844 -0
- metadata +295 -0
@@ -0,0 +1,203 @@
|
|
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
|
+
// == yale.h
|
25
|
+
//
|
26
|
+
// "new yale" storage format for 2D matrices (like yale, but with
|
27
|
+
// the diagonal pulled out for O(1) access).
|
28
|
+
//
|
29
|
+
// Specifications:
|
30
|
+
// * dtype and index dtype must necessarily differ
|
31
|
+
// * index dtype is defined by whatever unsigned type can store
|
32
|
+
// max(rows,cols)
|
33
|
+
// * that means vector ija stores only index dtype, but a stores
|
34
|
+
// dtype
|
35
|
+
// * vectors must be able to grow as necessary
|
36
|
+
// * maximum size is rows*cols+1
|
37
|
+
|
38
|
+
#ifndef YALE_H
|
39
|
+
#define YALE_H
|
40
|
+
|
41
|
+
/*
|
42
|
+
* Standard Includes
|
43
|
+
*/
|
44
|
+
|
45
|
+
#include <ruby.h>
|
46
|
+
#include <limits> // for std::numeric_limits<T>::max()
|
47
|
+
#include <stdexcept>
|
48
|
+
|
49
|
+
/*
|
50
|
+
* Project Includes
|
51
|
+
*/
|
52
|
+
|
53
|
+
#include "../../types.h"
|
54
|
+
#include "../../data/data.h"
|
55
|
+
#include "../common.h"
|
56
|
+
#include "../../nmatrix.h"
|
57
|
+
|
58
|
+
extern "C" {
|
59
|
+
|
60
|
+
/*
|
61
|
+
* Macros
|
62
|
+
*/
|
63
|
+
|
64
|
+
#ifndef NM_CHECK_ALLOC
|
65
|
+
#define NM_CHECK_ALLOC(x) if (!x) rb_raise(rb_eNoMemError, "insufficient memory");
|
66
|
+
#endif
|
67
|
+
|
68
|
+
/*
|
69
|
+
* Types
|
70
|
+
*/
|
71
|
+
|
72
|
+
|
73
|
+
/*
|
74
|
+
* Data
|
75
|
+
*/
|
76
|
+
|
77
|
+
|
78
|
+
/*
|
79
|
+
* Functions
|
80
|
+
*/
|
81
|
+
|
82
|
+
///////////////
|
83
|
+
// Lifecycle //
|
84
|
+
///////////////
|
85
|
+
|
86
|
+
YALE_STORAGE* nm_yale_storage_create(nm::dtype_t dtype, size_t* shape, size_t dim, size_t init_capacity);
|
87
|
+
YALE_STORAGE* nm_yale_storage_create_from_old_yale(nm::dtype_t dtype, size_t* shape, char* ia, char* ja, char* a, nm::dtype_t from_dtype);
|
88
|
+
YALE_STORAGE* nm_yale_storage_create_merged(const YALE_STORAGE* merge_template, const YALE_STORAGE* other);
|
89
|
+
void nm_yale_storage_delete(STORAGE* s);
|
90
|
+
void nm_yale_storage_delete_ref(STORAGE* s);
|
91
|
+
void nm_yale_storage_init(YALE_STORAGE* s, void* default_val);
|
92
|
+
void nm_yale_storage_mark(STORAGE*);
|
93
|
+
void nm_yale_storage_register(const STORAGE* s);
|
94
|
+
void nm_yale_storage_unregister(const STORAGE* s);
|
95
|
+
void nm_yale_storage_register_a(void* a, size_t size);
|
96
|
+
void nm_yale_storage_unregister_a(void* a, size_t size);
|
97
|
+
|
98
|
+
///////////////
|
99
|
+
// Accessors //
|
100
|
+
///////////////
|
101
|
+
|
102
|
+
VALUE nm_yale_each_with_indices(VALUE nmatrix);
|
103
|
+
VALUE nm_yale_each_stored_with_indices(VALUE nmatrix);
|
104
|
+
VALUE nm_yale_stored_diagonal_each_with_indices(VALUE nmatrix);
|
105
|
+
VALUE nm_yale_stored_nondiagonal_each_with_indices(VALUE nmatrix);
|
106
|
+
VALUE nm_yale_each_ordered_stored_with_indices(VALUE nmatrix);
|
107
|
+
void* nm_yale_storage_get(const STORAGE* s, SLICE* slice);
|
108
|
+
void* nm_yale_storage_ref(const STORAGE* s, SLICE* slice);
|
109
|
+
void nm_yale_storage_set(VALUE left, SLICE* slice, VALUE right);
|
110
|
+
|
111
|
+
//char nm_yale_storage_vector_insert(YALE_STORAGE* s, size_t pos, size_t* js, void* vals, size_t n, bool struct_only, nm::dtype_t dtype, nm::itype_t itype);
|
112
|
+
//void nm_yale_storage_increment_ia_after(YALE_STORAGE* s, size_t ija_size, size_t i, size_t n);
|
113
|
+
|
114
|
+
size_t nm_yale_storage_get_size(const YALE_STORAGE* storage);
|
115
|
+
VALUE nm_yale_default_value(VALUE self);
|
116
|
+
VALUE nm_yale_map_stored(VALUE self);
|
117
|
+
VALUE nm_yale_map_merged_stored(VALUE left, VALUE right, VALUE init);
|
118
|
+
|
119
|
+
///////////
|
120
|
+
// Tests //
|
121
|
+
///////////
|
122
|
+
|
123
|
+
bool nm_yale_storage_eqeq(const STORAGE* left, const STORAGE* right);
|
124
|
+
|
125
|
+
//////////
|
126
|
+
// Math //
|
127
|
+
//////////
|
128
|
+
|
129
|
+
STORAGE* nm_yale_storage_matrix_multiply(const STORAGE_PAIR& casted_storage, size_t* resulting_shape, bool vector);
|
130
|
+
|
131
|
+
/////////////
|
132
|
+
// Utility //
|
133
|
+
/////////////
|
134
|
+
|
135
|
+
|
136
|
+
|
137
|
+
/////////////////////////
|
138
|
+
// Copying and Casting //
|
139
|
+
/////////////////////////
|
140
|
+
|
141
|
+
STORAGE* nm_yale_storage_cast_copy(const STORAGE* rhs, nm::dtype_t new_dtype, void*);
|
142
|
+
STORAGE* nm_yale_storage_copy_transposed(const STORAGE* rhs_base);
|
143
|
+
|
144
|
+
|
145
|
+
|
146
|
+
void nm_init_yale_functions(void);
|
147
|
+
|
148
|
+
VALUE nm_vector_set(int argc, VALUE* argv, VALUE self);
|
149
|
+
|
150
|
+
|
151
|
+
} // end of extern "C" block
|
152
|
+
|
153
|
+
namespace nm {
|
154
|
+
|
155
|
+
namespace yale_storage {
|
156
|
+
|
157
|
+
/*
|
158
|
+
* Typedefs
|
159
|
+
*/
|
160
|
+
|
161
|
+
typedef size_t IType;
|
162
|
+
|
163
|
+
|
164
|
+
/*
|
165
|
+
* Templated Functions
|
166
|
+
*/
|
167
|
+
|
168
|
+
int binary_search(YALE_STORAGE* s, IType left, IType right, IType key);
|
169
|
+
|
170
|
+
/*
|
171
|
+
* Clear out the D portion of the A vector (clearing the diagonal and setting
|
172
|
+
* the zero value).
|
173
|
+
*
|
174
|
+
* Note: This sets a literal 0 value. If your dtype is RUBYOBJ (a Ruby object),
|
175
|
+
* it'll actually be INT2FIX(0) instead of a string of NULLs. You can actually
|
176
|
+
* set a default for Ruby objects other than zero -- you generally want it to
|
177
|
+
* be Qfalse, Qnil, or INT2FIX(0). The last is the default.
|
178
|
+
*/
|
179
|
+
template <typename DType>
|
180
|
+
inline void clear_diagonal_and_zero(YALE_STORAGE* s, void* init_val) {
|
181
|
+
DType* a = reinterpret_cast<DType*>(s->a);
|
182
|
+
|
183
|
+
// Clear out the diagonal + one extra entry
|
184
|
+
if (init_val) {
|
185
|
+
for (size_t i = 0; i <= s->shape[0]; ++i) // insert Ruby zeros, falses, or whatever else.
|
186
|
+
a[i] = *reinterpret_cast<DType*>(init_val);
|
187
|
+
} else {
|
188
|
+
for (size_t i = 0; i <= s->shape[0]; ++i) // insert zeros.
|
189
|
+
a[i] = 0;
|
190
|
+
}
|
191
|
+
}
|
192
|
+
|
193
|
+
template <typename DType>
|
194
|
+
void init(YALE_STORAGE* s, void* init_val);
|
195
|
+
|
196
|
+
size_t get_size(const YALE_STORAGE* storage);
|
197
|
+
|
198
|
+
IType binary_search_left_boundary(const YALE_STORAGE* s, IType left, IType right, IType bound);
|
199
|
+
|
200
|
+
|
201
|
+
}} // end of namespace nm::yale_storage
|
202
|
+
|
203
|
+
#endif // YALE_H
|
data/ext/nmatrix/types.h
ADDED
@@ -0,0 +1,55 @@
|
|
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
|
+
// == types.h
|
25
|
+
//
|
26
|
+
// Definition of simple types used throughout NMatrix.
|
27
|
+
|
28
|
+
#ifndef NMATRIX_TYPES_H
|
29
|
+
#define NMATRIX_TYPES_H
|
30
|
+
|
31
|
+
/*
|
32
|
+
* Standard Includes
|
33
|
+
*/
|
34
|
+
|
35
|
+
#include <ruby.h>
|
36
|
+
#include <cstdint>
|
37
|
+
|
38
|
+
/*
|
39
|
+
* Macros
|
40
|
+
*/
|
41
|
+
|
42
|
+
#define EPSILON 1E-10
|
43
|
+
#define FP_IS_ZERO(n) (-EPSILON < n && n < EPSILON)
|
44
|
+
#define FP_EQUAL(a, b) FP_IS_ZERO((a - b))
|
45
|
+
|
46
|
+
/*
|
47
|
+
* Types
|
48
|
+
*/
|
49
|
+
|
50
|
+
typedef float float32_t;
|
51
|
+
typedef double float64_t;
|
52
|
+
|
53
|
+
typedef size_t IType;
|
54
|
+
|
55
|
+
#endif
|
@@ -0,0 +1,279 @@
|
|
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
|
+
// == io.cpp
|
25
|
+
//
|
26
|
+
// Input/output support functions.
|
27
|
+
|
28
|
+
#include "io.h"
|
29
|
+
|
30
|
+
#include <ruby.h>
|
31
|
+
|
32
|
+
namespace nm { namespace io {
|
33
|
+
|
34
|
+
const char* const MATLAB_DTYPE_NAMES[NUM_MATLAB_DTYPES] = {
|
35
|
+
"miUNDEFINED0",
|
36
|
+
"miINT8",
|
37
|
+
"miUINT8",
|
38
|
+
"miINT16",
|
39
|
+
"miUINT16",
|
40
|
+
"miINT32",
|
41
|
+
"miUINT32",
|
42
|
+
"miSINGLE",
|
43
|
+
"miRESERVED8",
|
44
|
+
"miDOUBLE",
|
45
|
+
"miRESERVED10",
|
46
|
+
"miRESERVED11",
|
47
|
+
"miINT64",
|
48
|
+
"miUINT64",
|
49
|
+
"miMATRIX"
|
50
|
+
};
|
51
|
+
|
52
|
+
const size_t MATLAB_DTYPE_SIZES[NUM_MATLAB_DTYPES] = {
|
53
|
+
1, // undefined
|
54
|
+
1, // int8
|
55
|
+
1, // uint8
|
56
|
+
2, // int16
|
57
|
+
2, // uint16
|
58
|
+
4, // int32
|
59
|
+
4, // uint32
|
60
|
+
sizeof(float),
|
61
|
+
1, // reserved
|
62
|
+
sizeof(double),
|
63
|
+
1, // reserved
|
64
|
+
1, // reserved
|
65
|
+
8, // int64
|
66
|
+
8, // uint64
|
67
|
+
1 // matlab array?
|
68
|
+
};
|
69
|
+
|
70
|
+
|
71
|
+
/*
|
72
|
+
* Templated function for converting from MATLAB dtypes to NMatrix dtypes.
|
73
|
+
*/
|
74
|
+
template <typename DType, typename MDType>
|
75
|
+
char* matlab_cstring_to_dtype_string(size_t& result_len, const char* str, size_t bytes) {
|
76
|
+
|
77
|
+
result_len = sizeof(DType) * bytes / sizeof(MDType);
|
78
|
+
char* result = NM_ALLOC_N(char, result_len);
|
79
|
+
|
80
|
+
if (bytes % sizeof(MDType) != 0) {
|
81
|
+
rb_raise(rb_eArgError, "the given string does not divide evenly for the given MATLAB dtype");
|
82
|
+
}
|
83
|
+
|
84
|
+
for (size_t i = 0, j = 0; i < bytes; i += sizeof(MDType), j += sizeof(DType)) {
|
85
|
+
*reinterpret_cast<DType*>(result+j) = (DType)(*reinterpret_cast<const MDType*>(str + i));
|
86
|
+
}
|
87
|
+
|
88
|
+
return result;
|
89
|
+
}
|
90
|
+
|
91
|
+
|
92
|
+
|
93
|
+
}} // end of namespace nm::io
|
94
|
+
|
95
|
+
extern "C" {
|
96
|
+
|
97
|
+
///////////////////////
|
98
|
+
// Utility Functions //
|
99
|
+
///////////////////////
|
100
|
+
|
101
|
+
/*
|
102
|
+
* Converts a string to a data type.
|
103
|
+
*/
|
104
|
+
nm::dtype_t nm_dtype_from_rbstring(VALUE str) {
|
105
|
+
|
106
|
+
for (size_t index = 0; index < NM_NUM_DTYPES; ++index) {
|
107
|
+
if (!std::strncmp(RSTRING_PTR(str), DTYPE_NAMES[index], RSTRING_LEN(str))) {
|
108
|
+
return static_cast<nm::dtype_t>(index);
|
109
|
+
}
|
110
|
+
}
|
111
|
+
|
112
|
+
rb_raise(rb_eArgError, "invalid data type string (%s) specified", RSTRING_PTR(str));
|
113
|
+
}
|
114
|
+
|
115
|
+
|
116
|
+
/*
|
117
|
+
* Converts a symbol to a data type.
|
118
|
+
*/
|
119
|
+
nm::dtype_t nm_dtype_from_rbsymbol(VALUE sym) {
|
120
|
+
ID sym_id = SYM2ID(sym);
|
121
|
+
|
122
|
+
for (size_t index = 0; index < NM_NUM_DTYPES; ++index) {
|
123
|
+
if (sym_id == rb_intern(DTYPE_NAMES[index])) {
|
124
|
+
return static_cast<nm::dtype_t>(index);
|
125
|
+
}
|
126
|
+
}
|
127
|
+
|
128
|
+
VALUE str = rb_any_to_s(sym);
|
129
|
+
rb_raise(rb_eArgError, "invalid data type symbol (:%s) specified", RSTRING_PTR(str));
|
130
|
+
}
|
131
|
+
|
132
|
+
|
133
|
+
/*
|
134
|
+
* Converts a string to a storage type. Only looks at the first three
|
135
|
+
* characters.
|
136
|
+
*/
|
137
|
+
nm::stype_t nm_stype_from_rbstring(VALUE str) {
|
138
|
+
|
139
|
+
for (size_t index = 0; index < NM_NUM_STYPES; ++index) {
|
140
|
+
if (!std::strncmp(RSTRING_PTR(str), STYPE_NAMES[index], 3)) {
|
141
|
+
return static_cast<nm::stype_t>(index);
|
142
|
+
}
|
143
|
+
}
|
144
|
+
|
145
|
+
rb_raise(rb_eArgError, "Invalid storage type string specified");
|
146
|
+
return nm::DENSE_STORE;
|
147
|
+
}
|
148
|
+
|
149
|
+
/*
|
150
|
+
* Converts a symbol to a storage type.
|
151
|
+
*/
|
152
|
+
nm::stype_t nm_stype_from_rbsymbol(VALUE sym) {
|
153
|
+
|
154
|
+
for (size_t index = 0; index < NM_NUM_STYPES; ++index) {
|
155
|
+
if (SYM2ID(sym) == rb_intern(STYPE_NAMES[index])) {
|
156
|
+
return static_cast<nm::stype_t>(index);
|
157
|
+
}
|
158
|
+
}
|
159
|
+
|
160
|
+
VALUE str = rb_any_to_s(sym);
|
161
|
+
rb_raise(rb_eArgError, "invalid storage type symbol (:%s) specified", RSTRING_PTR(str));
|
162
|
+
return nm::DENSE_STORE;
|
163
|
+
}
|
164
|
+
|
165
|
+
|
166
|
+
/*
|
167
|
+
* Converts a MATLAB data-type symbol to an enum.
|
168
|
+
*/
|
169
|
+
static nm::io::matlab_dtype_t matlab_dtype_from_rbsymbol(VALUE sym) {
|
170
|
+
for (size_t index = 0; index < nm::io::NUM_MATLAB_DTYPES; ++index) {
|
171
|
+
if (SYM2ID(sym) == rb_intern(nm::io::MATLAB_DTYPE_NAMES[index])) {
|
172
|
+
return static_cast<nm::io::matlab_dtype_t>(index);
|
173
|
+
}
|
174
|
+
}
|
175
|
+
|
176
|
+
rb_raise(rb_eArgError, "Invalid matlab type specified.");
|
177
|
+
}
|
178
|
+
|
179
|
+
|
180
|
+
/*
|
181
|
+
* Take a string of bytes which represent MATLAB data type values and repack them into a string
|
182
|
+
* of bytes representing values of an NMatrix dtype (or itype).
|
183
|
+
*
|
184
|
+
* Returns what appears to be a Ruby String.
|
185
|
+
*
|
186
|
+
* Arguments:
|
187
|
+
* * str :: the data
|
188
|
+
* * from :: symbol representing MATLAB data type (e.g., :miINT8)
|
189
|
+
* * type :: either :itype or some dtype symbol (:byte, :uint32, etc)
|
190
|
+
*/
|
191
|
+
static VALUE nm_rbstring_matlab_repack(VALUE self, VALUE str, VALUE from, VALUE type) {
|
192
|
+
nm::io::matlab_dtype_t from_type = matlab_dtype_from_rbsymbol(from);
|
193
|
+
uint8_t to_type;
|
194
|
+
|
195
|
+
if (SYMBOL_P(type)) {
|
196
|
+
if (rb_to_id(type) == rb_intern("itype")) {
|
197
|
+
if (sizeof(size_t) == sizeof(int64_t)) {
|
198
|
+
to_type = static_cast<int8_t>(nm::INT64);
|
199
|
+
} else if (sizeof(size_t) == sizeof(int32_t)) {
|
200
|
+
to_type = static_cast<int8_t>(nm::INT32);
|
201
|
+
} else if (sizeof(size_t) == sizeof(int16_t)) {
|
202
|
+
to_type = static_cast<int8_t>(nm::INT16);
|
203
|
+
} else {
|
204
|
+
rb_raise(rb_eStandardError, "unhandled size_t definition");
|
205
|
+
}
|
206
|
+
} else {
|
207
|
+
to_type = static_cast<uint8_t>(nm_dtype_from_rbsymbol(type));
|
208
|
+
}
|
209
|
+
} else {
|
210
|
+
rb_raise(rb_eArgError, "expected symbol for third argument");
|
211
|
+
}
|
212
|
+
|
213
|
+
// For next few lines, see explanation above NM_MATLAB_DTYPE_TEMPLATE_TABLE definition in io.h.
|
214
|
+
if (to_type >= static_cast<uint8_t>(nm::COMPLEX64)) {
|
215
|
+
rb_raise(rb_eArgError, "can only repack into a simple dtype, no complex/VALUE");
|
216
|
+
}
|
217
|
+
|
218
|
+
// Do the actual repacking -- really simple!
|
219
|
+
NM_MATLAB_DTYPE_TEMPLATE_TABLE(ttable, nm::io::matlab_cstring_to_dtype_string, char*, size_t& result_len, const char* str, size_t bytes);
|
220
|
+
|
221
|
+
size_t repacked_data_length;
|
222
|
+
char* repacked_data = ttable[to_type][from_type](repacked_data_length, RSTRING_PTR(str), RSTRING_LEN(str));
|
223
|
+
|
224
|
+
// Encode as 8-bit ASCII with a length -- don't want to hiccup on \0
|
225
|
+
VALUE result = rb_str_new(repacked_data, repacked_data_length);
|
226
|
+
NM_FREE(repacked_data); // Don't forget to free what we allocated!
|
227
|
+
|
228
|
+
return result;
|
229
|
+
}
|
230
|
+
|
231
|
+
|
232
|
+
/*
|
233
|
+
* Take two byte-strings (real and imaginary) and treat them as if they contain
|
234
|
+
* a sequence of data of type dtype. Merge them together and return a new string.
|
235
|
+
*/
|
236
|
+
static VALUE nm_rbstring_merge(VALUE self, VALUE rb_real, VALUE rb_imaginary, VALUE rb_dtype) {
|
237
|
+
|
238
|
+
// Sanity check.
|
239
|
+
if (RSTRING_LEN(rb_real) != RSTRING_LEN(rb_imaginary)) {
|
240
|
+
rb_raise(rb_eArgError, "real and imaginary components do not have same length");
|
241
|
+
}
|
242
|
+
|
243
|
+
nm::dtype_t dtype = nm_dtype_from_rbsymbol(rb_dtype);
|
244
|
+
size_t len = DTYPE_SIZES[dtype];
|
245
|
+
|
246
|
+
char *real = RSTRING_PTR(rb_real),
|
247
|
+
*imag = RSTRING_PTR(rb_imaginary);
|
248
|
+
|
249
|
+
char* merge = NM_ALLOCA_N(char, RSTRING_LEN(rb_real)*2);
|
250
|
+
|
251
|
+
size_t merge_pos = 0;
|
252
|
+
|
253
|
+
// Merge the two sequences
|
254
|
+
for (size_t i = 0; i < (size_t)RSTRING_LEN(rb_real); i += len) {
|
255
|
+
|
256
|
+
// Copy real number
|
257
|
+
memcpy(merge + merge_pos, real + i, len);
|
258
|
+
merge_pos += len;
|
259
|
+
|
260
|
+
// Copy imaginary number
|
261
|
+
memcpy(merge + merge_pos, imag + i, len);
|
262
|
+
merge_pos += len;
|
263
|
+
}
|
264
|
+
|
265
|
+
return rb_str_new(merge, merge_pos);
|
266
|
+
}
|
267
|
+
|
268
|
+
|
269
|
+
void nm_init_io() {
|
270
|
+
cNMatrix_IO = rb_define_module_under(cNMatrix, "IO");
|
271
|
+
cNMatrix_IO_Matlab = rb_define_module_under(cNMatrix_IO, "Matlab");
|
272
|
+
|
273
|
+
rb_define_singleton_method(cNMatrix_IO_Matlab, "repack", (METHOD)nm_rbstring_matlab_repack, 3);
|
274
|
+
rb_define_singleton_method(cNMatrix_IO_Matlab, "complex_merge", (METHOD)nm_rbstring_merge, 3);
|
275
|
+
}
|
276
|
+
|
277
|
+
|
278
|
+
|
279
|
+
}
|
@@ -0,0 +1,115 @@
|
|
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
|
+
// == io.h
|
25
|
+
//
|
26
|
+
// Header file for input/output support functions.
|
27
|
+
|
28
|
+
#ifndef NMATRIX_IO_H
|
29
|
+
#define NMATRIX_IO_H
|
30
|
+
|
31
|
+
/*
|
32
|
+
* Project Includes
|
33
|
+
*/
|
34
|
+
|
35
|
+
#include "nmatrix.h"
|
36
|
+
|
37
|
+
#include "data/data.h"
|
38
|
+
#include "storage/storage.h"
|
39
|
+
|
40
|
+
/*
|
41
|
+
* Extern Types
|
42
|
+
*/
|
43
|
+
extern const char* const DTYPE_NAMES[nm::NUM_DTYPES];
|
44
|
+
|
45
|
+
namespace nm { namespace io {
|
46
|
+
/*
|
47
|
+
* Types
|
48
|
+
*/
|
49
|
+
enum matlab_dtype_t {
|
50
|
+
miINT8 = 1,
|
51
|
+
miUINT8 = 2,
|
52
|
+
miINT16 = 3,
|
53
|
+
miUINT16 = 4,
|
54
|
+
miINT32 = 5,
|
55
|
+
miUINT32 = 6,
|
56
|
+
miSINGLE = 7,
|
57
|
+
miDOUBLE = 9,
|
58
|
+
miINT64 = 12,
|
59
|
+
miUINT64 = 13,
|
60
|
+
miMATRIX = 14
|
61
|
+
};
|
62
|
+
|
63
|
+
/*
|
64
|
+
* Constants
|
65
|
+
*/
|
66
|
+
|
67
|
+
const size_t NUM_MATLAB_DTYPES = 15;
|
68
|
+
}} // end of namespace nm::io
|
69
|
+
|
70
|
+
extern "C" {
|
71
|
+
|
72
|
+
/*
|
73
|
+
* C accessors.
|
74
|
+
*/
|
75
|
+
nm::dtype_t nm_dtype_from_rbsymbol(VALUE sym);
|
76
|
+
nm::dtype_t nm_dtype_from_rbstring(VALUE str);
|
77
|
+
nm::stype_t nm_stype_from_rbsymbol(VALUE sym);
|
78
|
+
nm::stype_t nm_stype_from_rbstring(VALUE str);
|
79
|
+
|
80
|
+
void nm_init_io(void);
|
81
|
+
|
82
|
+
|
83
|
+
/*
|
84
|
+
* Macros.
|
85
|
+
*/
|
86
|
+
|
87
|
+
/*
|
88
|
+
* Macro for a function pointer table between NMatrix dtypes and MATLAB dtypes.
|
89
|
+
*
|
90
|
+
* You can't convert as freely between these two as you can between NMatrix dtypes, but there's no reason to. MATLAB
|
91
|
+
* stores its complex numbers in two separate arrays, for example, not as a single unit of data. If you want to convert
|
92
|
+
* to a VALUE, convert first to an appropriate integer or float type.
|
93
|
+
*
|
94
|
+
* FIXME: Maybe be a little more selective about which conversions we DO allow. This is really just for loading an
|
95
|
+
* already-constructed MATLAB matrix into memory, and most of these functions will never get called.
|
96
|
+
*/
|
97
|
+
#define NM_MATLAB_DTYPE_TEMPLATE_TABLE(name,fun,ret,...) \
|
98
|
+
static ret (*(name)[7][nm::io::NUM_MATLAB_DTYPES])(__VA_ARGS__) = { \
|
99
|
+
{ NULL, fun<uint8_t,int8_t>, fun<uint8_t,uint8_t>, fun<uint8_t,int16_t>, fun<uint8_t,uint16_t>, fun<uint8_t,int32_t>, fun<uint8_t,uint32_t>, fun<uint8_t,float>, NULL, fun<uint8_t,double>, NULL, NULL, fun<uint8_t,int64_t>, fun<uint8_t,uint64_t>, NULL }, \
|
100
|
+
{ NULL, fun<int8_t,int8_t>, fun<int8_t,uint8_t>, fun<int8_t,int16_t>, fun<int8_t,uint16_t>, fun<int8_t,int32_t>, fun<int8_t,uint32_t>, fun<int8_t,float>, NULL, fun<int8_t,double>, NULL, NULL, fun<int8_t,int64_t>, fun<int8_t,uint64_t>, NULL }, \
|
101
|
+
{ NULL, fun<int16_t,int8_t>, fun<int16_t,uint8_t>, fun<int16_t,int16_t>, fun<int16_t,uint16_t>, fun<int16_t,int32_t>, fun<int16_t,uint32_t>, fun<int16_t,float>, NULL, fun<int16_t,double>, NULL, NULL, fun<int16_t,int64_t>, fun<int16_t,uint64_t>, NULL }, \
|
102
|
+
{ NULL, fun<int32_t,int8_t>, fun<int32_t,uint8_t>, fun<int32_t,int16_t>, fun<int32_t,uint16_t>, fun<int32_t,int32_t>, fun<int32_t,uint32_t>, fun<int32_t,float>, NULL, fun<int32_t,double>, NULL, NULL, fun<int32_t,int64_t>, fun<int32_t,uint64_t>, NULL }, \
|
103
|
+
{ NULL, fun<int64_t,int8_t>, fun<int64_t,uint8_t>, fun<int64_t,int16_t>, fun<int64_t,uint16_t>, fun<int64_t,int32_t>, fun<int64_t,uint32_t>, fun<int64_t,float>, NULL, fun<int64_t,double>, NULL, NULL, fun<int64_t,int64_t>, fun<int64_t,uint64_t>, NULL }, \
|
104
|
+
{ NULL, fun<float,int8_t>, fun<float,uint8_t>, fun<float,int16_t>, fun<float,uint16_t>, fun<float,int32_t>, fun<float,uint32_t>, fun<float,float>, NULL, fun<float,double>, NULL, NULL, fun<float,int64_t>, fun<float,uint64_t>, NULL }, \
|
105
|
+
{ NULL, fun<double,int8_t>, fun<double,uint8_t>, fun<double,int16_t>, fun<double,uint16_t>, fun<double,int32_t>, fun<double,uint32_t>, fun<double,float>, NULL, fun<double,double>, NULL, NULL, fun<double,int64_t>, fun<double,uint64_t>, NULL } \
|
106
|
+
};
|
107
|
+
|
108
|
+
/*
|
109
|
+
* Hash#has_key? for symbols. Arguments are: hash (VALUE), string (char*).
|
110
|
+
*/
|
111
|
+
#define RB_HASH_HAS_SYMBOL_KEY(hash, str) (rb_funcall((hash), rb_intern("has_key?"), 1, ID2SYM(rb_intern(str))) == Qtrue)
|
112
|
+
}
|
113
|
+
|
114
|
+
|
115
|
+
#endif
|