nmatrix 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/Gemfile +1 -1
  2. data/History.txt +31 -3
  3. data/Manifest.txt +5 -0
  4. data/README.rdoc +29 -27
  5. data/ext/nmatrix/binary_format.txt +53 -0
  6. data/ext/nmatrix/data/data.cpp +18 -18
  7. data/ext/nmatrix/data/data.h +38 -7
  8. data/ext/nmatrix/data/rational.h +13 -0
  9. data/ext/nmatrix/data/ruby_object.h +10 -0
  10. data/ext/nmatrix/extconf.rb +2 -0
  11. data/ext/nmatrix/nmatrix.cpp +655 -103
  12. data/ext/nmatrix/nmatrix.h +26 -14
  13. data/ext/nmatrix/ruby_constants.cpp +4 -0
  14. data/ext/nmatrix/ruby_constants.h +2 -0
  15. data/ext/nmatrix/storage/dense.cpp +99 -41
  16. data/ext/nmatrix/storage/dense.h +3 -3
  17. data/ext/nmatrix/storage/list.cpp +36 -14
  18. data/ext/nmatrix/storage/list.h +4 -4
  19. data/ext/nmatrix/storage/storage.cpp +19 -19
  20. data/ext/nmatrix/storage/storage.h +11 -11
  21. data/ext/nmatrix/storage/yale.cpp +17 -20
  22. data/ext/nmatrix/storage/yale.h +13 -11
  23. data/ext/nmatrix/util/io.cpp +25 -23
  24. data/ext/nmatrix/util/io.h +5 -5
  25. data/ext/nmatrix/util/math.cpp +634 -17
  26. data/ext/nmatrix/util/math.h +958 -9
  27. data/ext/nmatrix/util/sl_list.cpp +7 -7
  28. data/ext/nmatrix/util/sl_list.h +2 -2
  29. data/lib/nmatrix.rb +9 -0
  30. data/lib/nmatrix/blas.rb +4 -4
  31. data/lib/nmatrix/io/market.rb +227 -0
  32. data/lib/nmatrix/io/mat_reader.rb +7 -7
  33. data/lib/nmatrix/lapack.rb +80 -0
  34. data/lib/nmatrix/nmatrix.rb +78 -52
  35. data/lib/nmatrix/shortcuts.rb +486 -0
  36. data/lib/nmatrix/version.rb +1 -1
  37. data/spec/2x2_dense_double.mat +0 -0
  38. data/spec/blas_spec.rb +59 -9
  39. data/spec/elementwise_spec.rb +25 -12
  40. data/spec/io_spec.rb +69 -1
  41. data/spec/lapack_spec.rb +53 -4
  42. data/spec/math_spec.rb +9 -0
  43. data/spec/nmatrix_list_spec.rb +95 -0
  44. data/spec/nmatrix_spec.rb +10 -53
  45. data/spec/nmatrix_yale_spec.rb +17 -15
  46. data/spec/shortcuts_spec.rb +154 -0
  47. metadata +22 -15
data/Gemfile CHANGED
@@ -2,4 +2,4 @@
2
2
  source "http://rubygems.org"
3
3
  gemspec
4
4
 
5
- gem 'packable' # for Matlab IO
5
+ gem 'packable', ">= 1.3.5" # for Matlab IO
@@ -6,7 +6,7 @@
6
6
 
7
7
  === 0.0.2 / 2012-09-21
8
8
 
9
- * Numerous major enhancements
9
+ * 15 major enhancements
10
10
 
11
11
  * Second alpha release
12
12
 
@@ -14,7 +14,7 @@
14
14
 
15
15
  * Added preliminary C API
16
16
 
17
- * Slicing and referencing support for dense and list matrices
17
+ * Slicing and referencing support for dense and list matrices (by @flipback)
18
18
 
19
19
  * BLAS level-3 xTRSM algorithm added for rationals and BLAS types
20
20
 
@@ -36,4 +36,32 @@
36
36
 
37
37
  * Sped up list storage item deletion, fixed bugs
38
38
 
39
- * Note: Element-wise list operations current disabled
39
+ * List matrix-to-hash conversion with `to_h`
40
+
41
+ * Note: Element-wise list operations current disabled
42
+
43
+ === 0.0.3 / 2013-01-18
44
+
45
+ * 8 major enhancements
46
+
47
+ * Matrix-scalar operations (dense, list)
48
+
49
+ * Shortcuts for matrix creation (by @agarie)
50
+
51
+ * Access to most ATLAS-implemented LAPACK functions for those with ATLAS' CLAPACK interface: xGETRF, xGETRI, xGETRS, xGESV, xPOTRF, xPOTRI, xPOTRS, xPOSV, xLASWP, xSCAL, xLAUUM
52
+
53
+ * Access to additional ATLAS-implemented BLAS functions: xTRMM, xSYRK, xHERK, xROT, xROTG
54
+
55
+ * Non-ATLAS versions of CLAPACK functions: xLASWP, xSCAL, xLAUUM, xROT
56
+
57
+ * Matrix inversion (LU and Cholesky; requires CLAPACK)
58
+
59
+ * LU factoring with and without CLAPACK
60
+
61
+ * Native matrix I/O for dense (supporting upper, lower, hermitian, skew, symmetric, and general) and yale (general only); excludes Ruby objects currently
62
+
63
+ * 2 bug fixes:
64
+
65
+ * Yale-to-list casting
66
+
67
+ * Now requires packable-1.3.5 or higher, fixing a problem with MATLAB .mat v5 file I/O (specific to doubles)
@@ -8,20 +8,25 @@ Guardfile
8
8
  spec/io_spec.rb
9
9
  spec/math_spec.rb
10
10
  spec/nmatrix_spec.rb
11
+ spec/nmatrix_list_spec.rb
11
12
  spec/nmatrix_yale_spec.rb
12
13
  spec/nvector_spec.rb
13
14
  spec/slice_spec.rb
15
+ spec/shortcuts_spec.rb
14
16
  spec/elementwise_spec.rb
15
17
  spec/blas_spec.rb
16
18
  spec/lapack_spec.rb
17
19
  spec/spec_helper.rb
18
20
  lib/nmatrix.rb
21
+ lib/nmatrix/io/market.rb
19
22
  lib/nmatrix/io/mat5_reader.rb
20
23
  lib/nmatrix/io/mat_reader.rb
21
24
  lib/nmatrix/blas.rb
25
+ lib/nmatrix/lapack.rb
22
26
  lib/nmatrix/monkeys.rb
23
27
  lib/nmatrix/nmatrix.rb
24
28
  lib/nmatrix/nvector.rb
29
+ lib/nmatrix/shortcuts.rb
25
30
  lib/nmatrix/version.rb
26
31
  ext/nmatrix/data/complex.h
27
32
  ext/nmatrix/data/data.cpp
@@ -27,49 +27,49 @@ are working on a {patch for Ruby/GSL}[https://github.com/SciRuby/rb-gsl].
27
27
 
28
28
  == Features
29
29
 
30
- The following features exist in the version of NMatrix (0.0.2) currently under development, and may or may not exist in
31
- 0.0.1 (the current gem):
30
+ The following features exist in the current version of NMatrix (0.0.2):
32
31
 
33
32
  * Matrix storage containers: dense, yale, list (more to come)
34
33
  * Data types: uint8, int8, int16, int32, int64, float32, float64, complex64, complex128, rational64, rational128
35
34
  (incomplete)
36
35
  * Conversion between storage and data types (except from-complex, and from-float-to-rational)
37
- * Element-wise operations and comparisons
36
+ * Element-wise operations and comparisons for dense and yale
38
37
  * Matrix-matrix multiplication for dense (using ATLAS) and yale
39
38
  * Matrix-vector multiplication for dense (using ATLAS)
40
39
  * Dense and list matrix slicing and referencing
40
+ * Native reading and writing of dense and yale matrices
41
+ * Optional compression for dense matrices with symmetry or triangularity: symmetric, skew, hermitian, upper, lower
41
42
  * Matlab .MAT v5 file input
42
43
  * C and C++ API
43
- * Level 3 BLAS internal implementations (no library) and ATLAS (with library) access:
44
- * xGEMM
45
- * xTRSM
44
+ * BLAS internal implementations (no library) and ATLAS (with library) access:
45
+ * Level 1: xROT, xROTG (BLAS dtypes only)
46
+ * Level 2: xGEMV
47
+ * Level 3: xGEMM, xTRSM
46
48
  * LAPACK ATLAS access:
47
- * xGETRF (experimental)
48
-
49
- === Planned Features (Very Short Term)
50
-
51
- These features will exist in our second alpha release, 0.0.2 (incomplete, thus not yet available as a gem):
52
-
53
- * Yale matrix slicing and referencing
54
- * LU decomposition
55
- * LAPACK internal implementations (no library needed):
49
+ * xGETRF, xGETRI, xGETRS, xGESV (Gaussian elimination)
50
+ * xPOTRF, xPOTRI, xPOTRS, xPOSV (Cholesky factorization)
51
+ * xLASWP, xSCAL, xLAUUM
52
+ * LAPACK-less internal implementations (no LAPACK needed and working on non-BLAS dtypes):
56
53
  * xGETRF
57
-
58
- The estimated release date for 0.0.2 is the end of August 2012.
54
+ * xLASWP, xSCAL
55
+ * xLAUUM (no LAPACK needed, but BLAS dtypes only)
56
+ * LU decomposition
57
+ * Matrix inversions (requires LAPACK; BLAS dtypes only)
58
+ * Determinant calculation for BLAS dtypes
59
59
 
60
60
  === Planned Features (Short-to-Medium Term)
61
61
 
62
62
  These are features planned for NMatrix 0.1.0, our first beta.
63
63
 
64
- * calculation of determinant, trace, and eigenvalues (characteristic polynomial) (0.1.0)
65
- * Gaussian elimination
64
+ * calculation of determinant (LAPACK-free), trace, and eigenvalues (characteristic polynomial) (0.1.0)
66
65
  * exponentials and square roots
67
- * matrix inversions
66
+ * matrix inversions (LAPACK-free)
68
67
  * matrix decomposition/factorization
69
68
  * calculation of norms
70
69
  * tensor products
71
70
  * principal component analysis (PCA)
72
71
  * improved file I/O
72
+ * compression of yale symmetries in I/O
73
73
  * operation scheduling
74
74
  * parallelization of some types of operations
75
75
  * optimization of non-BLAS data types on BLAS-like operations (e.g., matrix multiplication for rational numbers)
@@ -83,30 +83,32 @@ For full instructions, please see sciruby.com/nmatrix. Generally, you should be
83
83
 
84
84
  However, you will need to install ATLAS with CBLAS first. Those directions can be found at our website.
85
85
 
86
- NOTE: The above command will not give you 0.0.2, which is not yet complete. To obtain 0.0.2, you should use the
87
- following sequence of commands:
86
+ You can typically get the developer's build using the following sequence of commands:
88
87
 
89
88
  git clone https://github.com/SciRuby/nmatrix.git
90
89
  cd nmatrix/
91
90
  rake compile
92
91
  rake repackage
93
- gem install pkg/nmatrix-0.0.2.gem
92
+ gem install pkg/nmatrix-0.0.4.gem
94
93
 
95
94
  If you get errors about clapack.h or cblas.h, figure out where your ATLAS headers are using:
96
95
 
97
- locate clapack.h
96
+ locate clapack.h # If you're a Mac user, we recommend you search for cblas.h instead.
98
97
 
99
98
  Then, tell your system:
100
99
 
101
100
  export C_INCLUDE_PATH=/usr/local/atlas/include
101
+ export CPLUS_INCLUDE_PATH=/usr/local/atlas/include
102
102
 
103
103
  Finally, try compiling again.
104
104
 
105
105
  == REQUIREMENTS:
106
106
 
107
- * ATLAS and LAPACK, probably
108
- * GCC 4.2
107
+ * ATLAS
108
+ * LAPACK, probably
109
+ * GCC 4.3
109
110
  * Ruby 1.9
111
+ * {packable}[http://github.com/marcandre/packable] 1.3.5 (used for I/O)
110
112
 
111
113
  == INSTALLATION:
112
114
 
@@ -126,7 +128,7 @@ Before commiting any code, you *MUST* read our
126
128
 
127
129
  == LICENSE:
128
130
 
129
- Copyright (c) 2012, The Ruby Science Foundation.
131
+ Copyright (c) 2012--13, The Ruby Science Foundation.
130
132
 
131
133
  All rights reserved.
132
134
 
@@ -0,0 +1,53 @@
1
+ This is the proposed binary format for saving and loading NMatrix objects.
2
+
3
+ Order is little-endian.
4
+
5
+ List matrices should be converted to dense or yale matrices. There should be no serious need to load or save
6
+ linked-list matrices, since these exist primarily in order to construct efficient yale matrices.
7
+
8
+
9
+ First 64-bit block:
10
+ * ui16 major (version)
11
+ * ui16 minor
12
+ * ui16 release
13
+ * i16 NULL
14
+
15
+
16
+ Second 64-bit block:
17
+ * ui8 dtype
18
+ * ui8 stype
19
+ * ui8 itype # ui32 for dense
20
+ * ui8 symm
21
+ * i16 NULL
22
+ * ui16 dim # if 1, NVector; otherwise, NMatrix
23
+
24
+
25
+ 3rd - nth 64-bit block: shape
26
+
27
+ itype sets the number of bytes allocated for each shape entry. Since only yale uses itype, dense will pretty
28
+ much always be the UINT32 itype (see nmatrix.h). If the total number of bytes occupied by the shape array is
29
+ less than 8, the rest of the 64-bit block will be padded with zeros.
30
+
31
+
32
+ (n+1)th 64-bit block: depends on stype, symm
33
+
34
+ symm is designed to reduce file size by allowing us to not save certain elements in symmetric, hermitian, skew-
35
+ symmetric, and triangular matrices. These values will be defined in nmatrix.h; 0 indicates standard (no symmetry).
36
+ In later versions, additional patterns may be defined which might even have less to do with symmetry than
37
+ upper/lower do.
38
+
39
+ When storing a symmetric matrix, we will only store the upper portion. If the matrix is lower triangular, only the
40
+ lower portion will be stored.
41
+
42
+ For dense, we simply store the contents of the matrix exactly as in memory (or just the upper-triangular part if
43
+ symm is set).
44
+
45
+ For yale, we store:
46
+ * ui32 ndnz
47
+ * ui32 length (AKA size, the number of elements in A/IJA that aren't nil/undefined)
48
+
49
+ The latter will serve as the capacity when we read a Yale matrix.
50
+
51
+ Then we store the a array, again padding with zeros so it's a multiple of 8 bytes.
52
+
53
+ Then we store the ija array, padding with zeros so it's a multiple of 8 bytes.
@@ -95,20 +95,20 @@ const size_t ITYPE_SIZES[nm::NUM_ITYPES] = {
95
95
  sizeof(uint64_t),
96
96
  };
97
97
 
98
- const dtype_t Upcast[nm::NUM_DTYPES][nm::NUM_DTYPES] = {
99
- { BYTE, INT8, INT16, INT32, INT64, FLOAT32, FLOAT64, COMPLEX64, COMPLEX128, RATIONAL32, RATIONAL64, RATIONAL128, RUBYOBJ},
100
- { INT8, INT8, INT16, INT32, INT64, FLOAT32, FLOAT64, COMPLEX64, COMPLEX128, RATIONAL32, RATIONAL64, RATIONAL128, RUBYOBJ},
101
- { INT16, INT16, INT16, INT32, INT64, FLOAT32, FLOAT64, COMPLEX64, COMPLEX128, RATIONAL32, RATIONAL64, RATIONAL128, RUBYOBJ},
102
- { INT32, INT32, INT32, INT32, INT64, FLOAT32, FLOAT64, COMPLEX64, COMPLEX128, RATIONAL32, RATIONAL64, RATIONAL128, RUBYOBJ},
103
- { INT64, INT64, INT64, INT64, INT64, FLOAT32, FLOAT64, COMPLEX64, COMPLEX128, RATIONAL32, RATIONAL64, RATIONAL128, RUBYOBJ},
104
- { FLOAT32, FLOAT32, FLOAT32, FLOAT32, FLOAT32, FLOAT32, FLOAT64, COMPLEX64, COMPLEX128, FLOAT64, FLOAT64, FLOAT64, RUBYOBJ},
105
- { FLOAT64, FLOAT64, FLOAT64, FLOAT64, FLOAT64, FLOAT64, FLOAT64, COMPLEX128, COMPLEX128, FLOAT64, FLOAT64, FLOAT64, RUBYOBJ},
106
- { COMPLEX64, COMPLEX64, COMPLEX64, COMPLEX64, COMPLEX64, COMPLEX64, COMPLEX128, COMPLEX64, COMPLEX128, COMPLEX64, COMPLEX64, COMPLEX64, RUBYOBJ},
107
- { COMPLEX128, COMPLEX128, COMPLEX128, COMPLEX128, COMPLEX128, COMPLEX128, COMPLEX128, COMPLEX128, COMPLEX128, COMPLEX128, COMPLEX128, COMPLEX128, RUBYOBJ},
108
- { RATIONAL32, RATIONAL32, RATIONAL32, RATIONAL32, RATIONAL32, FLOAT64, FLOAT64, COMPLEX64, COMPLEX128, RATIONAL32, RATIONAL64, RATIONAL128, RUBYOBJ},
109
- { RATIONAL64, RATIONAL64, RATIONAL64, RATIONAL64, RATIONAL64, FLOAT64, FLOAT64, COMPLEX64, COMPLEX128, RATIONAL64, RATIONAL64, RATIONAL128, RUBYOBJ},
110
- { RATIONAL128, RATIONAL128, RATIONAL128, RATIONAL128, RATIONAL128, FLOAT64, FLOAT64, COMPLEX64, COMPLEX128, RATIONAL128, RATIONAL128, RATIONAL128, RUBYOBJ},
111
- { RUBYOBJ, RUBYOBJ, RUBYOBJ, RUBYOBJ, RUBYOBJ, RUBYOBJ, RUBYOBJ, RUBYOBJ, RUBYOBJ, RUBYOBJ, RUBYOBJ, RUBYOBJ, RUBYOBJ}
98
+ const nm::dtype_t Upcast[nm::NUM_DTYPES][nm::NUM_DTYPES] = {
99
+ { nm::BYTE, nm::INT8, nm::INT16, nm::INT32, nm::INT64, nm::FLOAT32, nm::FLOAT64, nm::COMPLEX64, nm::COMPLEX128, nm::RATIONAL32, nm::RATIONAL64, nm::RATIONAL128, nm::RUBYOBJ},
100
+ { nm::INT8, nm::INT8, nm::INT16, nm::INT32, nm::INT64, nm::FLOAT32, nm::FLOAT64, nm::COMPLEX64, nm::COMPLEX128, nm::RATIONAL32, nm::RATIONAL64, nm::RATIONAL128, nm::RUBYOBJ},
101
+ { nm::INT16, nm::INT16, nm::INT16, nm::INT32, nm::INT64, nm::FLOAT32, nm::FLOAT64, nm::COMPLEX64, nm::COMPLEX128, nm::RATIONAL32, nm::RATIONAL64, nm::RATIONAL128, nm::RUBYOBJ},
102
+ { nm::INT32, nm::INT32, nm::INT32, nm::INT32, nm::INT64, nm::FLOAT32, nm::FLOAT64, nm::COMPLEX64, nm::COMPLEX128, nm::RATIONAL32, nm::RATIONAL64, nm::RATIONAL128, nm::RUBYOBJ},
103
+ { nm::INT64, nm::INT64, nm::INT64, nm::INT64, nm::INT64, nm::FLOAT32, nm::FLOAT64, nm::COMPLEX64, nm::COMPLEX128, nm::RATIONAL32, nm::RATIONAL64, nm::RATIONAL128, nm::RUBYOBJ},
104
+ { nm::FLOAT32, nm::FLOAT32, nm::FLOAT32, nm::FLOAT32, nm::FLOAT32, nm::FLOAT32, nm::FLOAT64, nm::COMPLEX64, nm::COMPLEX128, nm::FLOAT64, nm::FLOAT64, nm::FLOAT64, nm::RUBYOBJ},
105
+ { nm::FLOAT64, nm::FLOAT64, nm::FLOAT64, nm::FLOAT64, nm::FLOAT64, nm::FLOAT64, nm::FLOAT64, nm::COMPLEX128, nm::COMPLEX128, nm::FLOAT64, nm::FLOAT64, nm::FLOAT64, nm::RUBYOBJ},
106
+ { nm::COMPLEX64, nm::COMPLEX64, nm::COMPLEX64, nm::COMPLEX64, nm::COMPLEX64, nm::COMPLEX64, nm::COMPLEX128, nm::COMPLEX64, nm::COMPLEX128, nm::COMPLEX64, nm::COMPLEX64, nm::COMPLEX64, nm::RUBYOBJ},
107
+ { nm::COMPLEX128, nm::COMPLEX128, nm::COMPLEX128, nm::COMPLEX128, nm::COMPLEX128, nm::COMPLEX128, nm::COMPLEX128, nm::COMPLEX128, nm::COMPLEX128, nm::COMPLEX128, nm::COMPLEX128, nm::COMPLEX128, nm::RUBYOBJ},
108
+ { nm::RATIONAL32, nm::RATIONAL32, nm::RATIONAL32, nm::RATIONAL32, nm::RATIONAL32, nm::FLOAT64, nm::FLOAT64, nm::COMPLEX64, nm::COMPLEX128, nm::RATIONAL32, nm::RATIONAL64, nm::RATIONAL128, nm::RUBYOBJ},
109
+ { nm::RATIONAL64, nm::RATIONAL64, nm::RATIONAL64, nm::RATIONAL64, nm::RATIONAL64, nm::FLOAT64, nm::FLOAT64, nm::COMPLEX64, nm::COMPLEX128, nm::RATIONAL64, nm::RATIONAL64, nm::RATIONAL128, nm::RUBYOBJ},
110
+ { nm::RATIONAL128, nm::RATIONAL128, nm::RATIONAL128, nm::RATIONAL128, nm::RATIONAL128, nm::FLOAT64, nm::FLOAT64, nm::COMPLEX64, nm::COMPLEX128, nm::RATIONAL128, nm::RATIONAL128, nm::RATIONAL128, nm::RUBYOBJ},
111
+ { nm::RUBYOBJ, nm::RUBYOBJ, nm::RUBYOBJ, nm::RUBYOBJ, nm::RUBYOBJ, nm::RUBYOBJ, nm::RUBYOBJ, nm::RUBYOBJ, nm::RUBYOBJ, nm::RUBYOBJ, nm::RUBYOBJ, nm::RUBYOBJ, nm::RUBYOBJ}
112
112
  };
113
113
 
114
114
 
@@ -123,7 +123,7 @@ const dtype_t Upcast[nm::NUM_DTYPES][nm::NUM_DTYPES] = {
123
123
  /*
124
124
  * Converts a RubyObject
125
125
  */
126
- void rubyval_to_cval(VALUE val, dtype_t dtype, void* loc) {
126
+ void rubyval_to_cval(VALUE val, nm::dtype_t dtype, void* loc) {
127
127
  using namespace nm;
128
128
  switch (dtype) {
129
129
  case BYTE:
@@ -189,7 +189,7 @@ void rubyval_to_cval(VALUE val, dtype_t dtype, void* loc) {
189
189
  * Create a RubyObject from a regular C value (given a dtype). Does not return a VALUE! To get a VALUE, you need to
190
190
  * look at the rval property of what this function returns.
191
191
  */
192
- nm::RubyObject rubyobj_from_cval(void* val, dtype_t dtype) {
192
+ nm::RubyObject rubyobj_from_cval(void* val, nm::dtype_t dtype) {
193
193
  using namespace nm;
194
194
  switch (dtype) {
195
195
  case BYTE:
@@ -238,7 +238,7 @@ nm::RubyObject rubyobj_from_cval(void* val, dtype_t dtype) {
238
238
  /*
239
239
  * Convert from itype instead of dtype
240
240
  */
241
- nm::RubyObject rubyobj_from_cval_by_itype(void* val, itype_t itype) {
241
+ nm::RubyObject rubyobj_from_cval_by_itype(void* val, nm::itype_t itype) {
242
242
  using namespace nm;
243
243
  switch (itype) {
244
244
  case UINT8:
@@ -263,7 +263,7 @@ nm::RubyObject rubyobj_from_cval_by_itype(void* val, itype_t itype) {
263
263
  * Allocate and return a piece of data of the correct dtype, converted from a
264
264
  * given RubyObject.
265
265
  */
266
- void* rubyobj_to_cval(VALUE val, dtype_t dtype) {
266
+ void* rubyobj_to_cval(VALUE val, nm::dtype_t dtype) {
267
267
  size_t size = DTYPE_SIZES[dtype];
268
268
  void* ret_val = ALLOC_N(char, size);
269
269
 
@@ -82,7 +82,7 @@ namespace nm {
82
82
  };
83
83
 
84
84
  #define STYPE_CAST_COPY_TABLE(name) \
85
- static STORAGE* (*(name)[nm::NUM_STYPES][nm::NUM_STYPES])(const STORAGE*, dtype_t) = { \
85
+ static STORAGE* (*(name)[nm::NUM_STYPES][nm::NUM_STYPES])(const STORAGE*, nm::dtype_t) = { \
86
86
  { nm_dense_storage_cast_copy, nm_dense_storage_from_list, nm_dense_storage_from_yale }, \
87
87
  { nm_list_storage_from_dense, nm_list_storage_cast_copy, nm_list_storage_from_yale }, \
88
88
  { nm_yale_storage_from_dense, nm_yale_storage_from_list, nm_yale_storage_cast_copy } \
@@ -95,6 +95,22 @@ namespace nm {
95
95
  #define DTYPE_TEMPLATE_TABLE(fun, ret, ...) NAMED_DTYPE_TEMPLATE_TABLE(ttable, fun, ret, __VA_ARGS__)
96
96
 
97
97
  #define NAMED_DTYPE_TEMPLATE_TABLE(name, fun, ret, ...) \
98
+ static ret (*(name)[nm::NUM_DTYPES])(__VA_ARGS__) = { \
99
+ fun<uint8_t>, \
100
+ fun<int8_t>, \
101
+ fun<int16_t>, \
102
+ fun<int32_t>, \
103
+ fun<int64_t>, \
104
+ fun<float32_t>, \
105
+ fun<float64_t>, \
106
+ fun<nm::Complex64>, \
107
+ fun<nm::Complex128>, \
108
+ fun<nm::Rational32>, \
109
+ fun<nm::Rational64>, \
110
+ fun<nm::Rational128> \
111
+ };
112
+
113
+ #define NAMED_DTYPE_TEMPLATE_TABLE_NO_ROBJ(name, fun, ret, ...) \
98
114
  static ret (*(name)[nm::NUM_DTYPES])(__VA_ARGS__) = { \
99
115
  fun<uint8_t>, \
100
116
  fun<int8_t>, \
@@ -108,7 +124,6 @@ namespace nm {
108
124
  fun<nm::Rational32>, \
109
125
  fun<nm::Rational64>, \
110
126
  fun<nm::Rational128>, \
111
- fun<nm::RubyObject> \
112
127
  };
113
128
 
114
129
  /*
@@ -674,6 +689,22 @@ static ret (*(name)[nm::NUM_DTYPES][nm::NUM_DTYPES][nm::NUM_ITYPES])(__VA_ARGS__
674
689
  { fun<nm::RubyObject,uint8_t>,fun<nm::RubyObject,uint16_t>,fun<nm::RubyObject,uint32_t>,fun<nm::RubyObject,uint64_t>} \
675
690
  };
676
691
 
692
+ #define NAMED_LI_DTYPE_TEMPLATE_TABLE_NO_ROBJ(name, fun, ret, ...) \
693
+ static ret (*(name)[nm::NUM_DTYPES][nm::NUM_ITYPES])(__VA_ARGS__) = { \
694
+ { fun<uint8_t,uint8_t>,fun<uint8_t,uint16_t>,fun<uint8_t,uint32_t>,fun<uint8_t,uint64_t> }, \
695
+ { fun<int8_t,uint8_t>,fun<int8_t,uint16_t>,fun<int8_t,uint32_t>,fun<int8_t,uint64_t> }, \
696
+ { fun<int16_t,uint8_t>,fun<int16_t,uint16_t>,fun<int16_t,uint32_t>,fun<int16_t,uint64_t> }, \
697
+ { fun<int32_t,uint8_t>,fun<int32_t,uint16_t>,fun<int32_t,uint32_t>,fun<int32_t,uint64_t> }, \
698
+ { fun<int64_t,uint8_t>,fun<int64_t,uint16_t>,fun<int64_t,uint32_t>,fun<int64_t,uint64_t> }, \
699
+ { fun<float32_t,uint8_t>,fun<float32_t,uint16_t>,fun<float32_t,uint32_t>,fun<float32_t,uint64_t> }, \
700
+ { fun<float64_t,uint8_t>,fun<float64_t,uint16_t>,fun<float64_t,uint32_t>,fun<float64_t,uint64_t> }, \
701
+ { fun<nm::Complex64,uint8_t>,fun<nm::Complex64,uint16_t>,fun<nm::Complex64,uint32_t>,fun<nm::Complex64,uint64_t> }, \
702
+ { fun<nm::Complex128,uint8_t>,fun<nm::Complex128,uint16_t>,fun<nm::Complex128,uint32_t>,fun<nm::Complex128,uint64_t> }, \
703
+ { fun<nm::Rational32,uint8_t>,fun<nm::Rational32,uint16_t>,fun<nm::Rational32,uint32_t>,fun<nm::Rational32,uint64_t> }, \
704
+ { fun<nm::Rational64,uint8_t>,fun<nm::Rational64,uint16_t>,fun<nm::Rational64,uint32_t>,fun<nm::Rational64,uint64_t> }, \
705
+ { fun<nm::Rational128,uint8_t>,fun<nm::Rational128,uint16_t>,fun<nm::Rational128,uint32_t>,fun<nm::Rational128,uint64_t> } \
706
+ };
707
+
677
708
 
678
709
  extern "C" {
679
710
 
@@ -690,17 +721,17 @@ extern const size_t DTYPE_SIZES[nm::NUM_DTYPES];
690
721
  extern const char* const ITYPE_NAMES[nm::NUM_ITYPES];
691
722
  extern const size_t ITYPE_SIZES[nm::NUM_ITYPES];
692
723
 
693
- extern const dtype_t Upcast[nm::NUM_DTYPES][nm::NUM_DTYPES];
724
+ extern const nm::dtype_t Upcast[nm::NUM_DTYPES][nm::NUM_DTYPES];
694
725
 
695
726
  /*
696
727
  * Functions
697
728
  */
698
729
 
699
730
 
700
- void* rubyobj_to_cval(VALUE val, dtype_t dtype);
701
- void rubyval_to_cval(VALUE val, dtype_t dtype, void* loc);
702
- nm::RubyObject rubyobj_from_cval(void* val, dtype_t dtype);
703
- nm::RubyObject rubyobj_from_cval_by_itype(void* val, itype_t itype);
731
+ void* rubyobj_to_cval(VALUE val, nm::dtype_t dtype);
732
+ void rubyval_to_cval(VALUE val, nm::dtype_t dtype, void* loc);
733
+ nm::RubyObject rubyobj_from_cval(void* val, nm::dtype_t dtype);
734
+ nm::RubyObject rubyobj_from_cval_by_itype(void* val, nm::itype_t itype);
704
735
 
705
736
  } // end of extern "C" block
706
737
 
@@ -304,6 +304,12 @@ class Rational {
304
304
  }
305
305
  };
306
306
 
307
+ // Negative operator
308
+ template <typename Type, typename = typename std::enable_if<std::is_integral<Type>::value>::type>
309
+ inline Rational<Type> operator-(const Rational<Type>& rhs) {
310
+ return Rational<Type>(-rhs.n, rhs.d);
311
+ }
312
+
307
313
  ////////////////////////////////
308
314
  // Native-Rational Operations //
309
315
  ////////////////////////////////
@@ -416,6 +422,13 @@ namespace std {
416
422
  if (value.n >= 0) return value;
417
423
  return nm::Rational<IntType>(-value.n, value.d);
418
424
  }
425
+
426
+ template <typename IntType, typename = typename std::enable_if<std::is_integral<IntType>::value>::type>
427
+ nm::Rational<IntType> sqrt(const nm::Rational<IntType>& value) {
428
+ nm::Rational<IntType> result(std::sqrt(value.n), std::sqrt(value.d));
429
+ if (value * value == result) return result;
430
+ else rb_raise(rb_eArgError, "square root of the given rational is not rational");
431
+ }
419
432
  }
420
433
 
421
434
  #endif // RATIONAL_H
@@ -319,6 +319,11 @@ class RubyObject {
319
319
  }
320
320
  };
321
321
 
322
+ // Negative operator
323
+ inline RubyObject operator-(const RubyObject& rhs) {
324
+ return RubyObject(rb_funcall(rhs.rval, nm_rb_negate, 0));
325
+ }
326
+
322
327
 
323
328
  ////////////////////////////
324
329
  // NATIVE-RUBY OPERATIONS //
@@ -441,6 +446,11 @@ namespace std {
441
446
  inline nm::RubyObject abs(const nm::RubyObject& obj) {
442
447
  return obj.abs();
443
448
  }
449
+
450
+ inline nm::RubyObject sqrt(const nm::RubyObject& obj) {
451
+ VALUE cMath = rb_const_get(rb_cObject, rb_intern("Math"));
452
+ return nm::RubyObject(rb_funcall(cMath, rb_intern("sqrt"), 1, obj.rval));
453
+ }
444
454
  }
445
455
 
446
456
  #endif // RUBY_OBJECT_H