pnmatrix 1.2.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (111) hide show
  1. checksums.yaml +7 -0
  2. data/ext/nmatrix/binary_format.txt +53 -0
  3. data/ext/nmatrix/data/complex.h +388 -0
  4. data/ext/nmatrix/data/data.cpp +274 -0
  5. data/ext/nmatrix/data/data.h +651 -0
  6. data/ext/nmatrix/data/meta.h +64 -0
  7. data/ext/nmatrix/data/ruby_object.h +386 -0
  8. data/ext/nmatrix/extconf.rb +70 -0
  9. data/ext/nmatrix/math/asum.h +99 -0
  10. data/ext/nmatrix/math/cblas_enums.h +36 -0
  11. data/ext/nmatrix/math/cblas_templates_core.h +507 -0
  12. data/ext/nmatrix/math/gemm.h +241 -0
  13. data/ext/nmatrix/math/gemv.h +178 -0
  14. data/ext/nmatrix/math/getrf.h +255 -0
  15. data/ext/nmatrix/math/getrs.h +121 -0
  16. data/ext/nmatrix/math/imax.h +82 -0
  17. data/ext/nmatrix/math/laswp.h +165 -0
  18. data/ext/nmatrix/math/long_dtype.h +62 -0
  19. data/ext/nmatrix/math/magnitude.h +54 -0
  20. data/ext/nmatrix/math/math.h +751 -0
  21. data/ext/nmatrix/math/nrm2.h +165 -0
  22. data/ext/nmatrix/math/rot.h +117 -0
  23. data/ext/nmatrix/math/rotg.h +106 -0
  24. data/ext/nmatrix/math/scal.h +71 -0
  25. data/ext/nmatrix/math/trsm.h +336 -0
  26. data/ext/nmatrix/math/util.h +162 -0
  27. data/ext/nmatrix/math.cpp +1368 -0
  28. data/ext/nmatrix/nm_memory.h +60 -0
  29. data/ext/nmatrix/nmatrix.cpp +285 -0
  30. data/ext/nmatrix/nmatrix.h +476 -0
  31. data/ext/nmatrix/ruby_constants.cpp +151 -0
  32. data/ext/nmatrix/ruby_constants.h +106 -0
  33. data/ext/nmatrix/ruby_nmatrix.c +3130 -0
  34. data/ext/nmatrix/storage/common.cpp +77 -0
  35. data/ext/nmatrix/storage/common.h +183 -0
  36. data/ext/nmatrix/storage/dense/dense.cpp +1096 -0
  37. data/ext/nmatrix/storage/dense/dense.h +129 -0
  38. data/ext/nmatrix/storage/list/list.cpp +1628 -0
  39. data/ext/nmatrix/storage/list/list.h +138 -0
  40. data/ext/nmatrix/storage/storage.cpp +730 -0
  41. data/ext/nmatrix/storage/storage.h +99 -0
  42. data/ext/nmatrix/storage/yale/class.h +1139 -0
  43. data/ext/nmatrix/storage/yale/iterators/base.h +143 -0
  44. data/ext/nmatrix/storage/yale/iterators/iterator.h +131 -0
  45. data/ext/nmatrix/storage/yale/iterators/row.h +450 -0
  46. data/ext/nmatrix/storage/yale/iterators/row_stored.h +140 -0
  47. data/ext/nmatrix/storage/yale/iterators/row_stored_nd.h +169 -0
  48. data/ext/nmatrix/storage/yale/iterators/stored_diagonal.h +124 -0
  49. data/ext/nmatrix/storage/yale/math/transpose.h +110 -0
  50. data/ext/nmatrix/storage/yale/yale.cpp +2074 -0
  51. data/ext/nmatrix/storage/yale/yale.h +203 -0
  52. data/ext/nmatrix/types.h +55 -0
  53. data/ext/nmatrix/util/io.cpp +279 -0
  54. data/ext/nmatrix/util/io.h +115 -0
  55. data/ext/nmatrix/util/sl_list.cpp +627 -0
  56. data/ext/nmatrix/util/sl_list.h +144 -0
  57. data/ext/nmatrix/util/util.h +78 -0
  58. data/lib/nmatrix/blas.rb +378 -0
  59. data/lib/nmatrix/cruby/math.rb +744 -0
  60. data/lib/nmatrix/enumerate.rb +253 -0
  61. data/lib/nmatrix/homogeneous.rb +241 -0
  62. data/lib/nmatrix/io/fortran_format.rb +138 -0
  63. data/lib/nmatrix/io/harwell_boeing.rb +221 -0
  64. data/lib/nmatrix/io/market.rb +263 -0
  65. data/lib/nmatrix/io/point_cloud.rb +189 -0
  66. data/lib/nmatrix/jruby/decomposition.rb +24 -0
  67. data/lib/nmatrix/jruby/enumerable.rb +13 -0
  68. data/lib/nmatrix/jruby/error.rb +4 -0
  69. data/lib/nmatrix/jruby/math.rb +501 -0
  70. data/lib/nmatrix/jruby/nmatrix_java.rb +840 -0
  71. data/lib/nmatrix/jruby/operators.rb +283 -0
  72. data/lib/nmatrix/jruby/slice.rb +264 -0
  73. data/lib/nmatrix/lapack_core.rb +181 -0
  74. data/lib/nmatrix/lapack_plugin.rb +44 -0
  75. data/lib/nmatrix/math.rb +953 -0
  76. data/lib/nmatrix/mkmf.rb +100 -0
  77. data/lib/nmatrix/monkeys.rb +137 -0
  78. data/lib/nmatrix/nmatrix.rb +1172 -0
  79. data/lib/nmatrix/rspec.rb +75 -0
  80. data/lib/nmatrix/shortcuts.rb +1163 -0
  81. data/lib/nmatrix/version.rb +39 -0
  82. data/lib/nmatrix/yale_functions.rb +118 -0
  83. data/lib/nmatrix.rb +28 -0
  84. data/spec/00_nmatrix_spec.rb +892 -0
  85. data/spec/01_enum_spec.rb +196 -0
  86. data/spec/02_slice_spec.rb +407 -0
  87. data/spec/03_nmatrix_monkeys_spec.rb +80 -0
  88. data/spec/2x2_dense_double.mat +0 -0
  89. data/spec/4x4_sparse.mat +0 -0
  90. data/spec/4x5_dense.mat +0 -0
  91. data/spec/blas_spec.rb +215 -0
  92. data/spec/elementwise_spec.rb +311 -0
  93. data/spec/homogeneous_spec.rb +100 -0
  94. data/spec/io/fortran_format_spec.rb +88 -0
  95. data/spec/io/harwell_boeing_spec.rb +98 -0
  96. data/spec/io/test.rua +9 -0
  97. data/spec/io_spec.rb +159 -0
  98. data/spec/lapack_core_spec.rb +482 -0
  99. data/spec/leakcheck.rb +16 -0
  100. data/spec/math_spec.rb +1363 -0
  101. data/spec/nmatrix_yale_resize_test_associations.yaml +2802 -0
  102. data/spec/nmatrix_yale_spec.rb +286 -0
  103. data/spec/rspec_monkeys.rb +56 -0
  104. data/spec/rspec_spec.rb +35 -0
  105. data/spec/shortcuts_spec.rb +474 -0
  106. data/spec/slice_set_spec.rb +162 -0
  107. data/spec/spec_helper.rb +172 -0
  108. data/spec/stat_spec.rb +214 -0
  109. data/spec/test.pcd +20 -0
  110. data/spec/utm5940.mtx +83844 -0
  111. metadata +295 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: be16fe762b002a63a7d2542fb5eb50ed02cf9fd86bc9bb783a480dbeee9aca8a
4
+ data.tar.gz: c0427a16637c1ed803ce4249d238ef419a903340f81e9705d59f99cd376697ad
5
+ SHA512:
6
+ metadata.gz: 215cd7e47e75a13afb836e630a61d2f34057452601ca7cd9a70dd9a216258cd0b0763d6c064e36754475833c0ff8cec0144bdedf36f774d65a6498ae705c4954
7
+ data.tar.gz: b6f3078f05c24952b3dc8bab939a9b5f63cd673bda80450c5e229cc909913382d71adb5e9ff361a293c7e762ea741d0bc78d509567fc52fcdd1b13bb840e5670
@@ -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.
@@ -0,0 +1,388 @@
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
+ // == complex.h
25
+ //
26
+ // Functions and classes for dealing with complex numbers.
27
+
28
+ #ifndef COMPLEX_H
29
+ #define COMPLEX_H
30
+
31
+ /*
32
+ * Standard Includes
33
+ */
34
+
35
+ #include <ruby.h>
36
+ #include <type_traits>
37
+ #include <iostream>
38
+ #include <cmath>
39
+
40
+ /*
41
+ * Project Includes
42
+ */
43
+
44
+ #include "types.h"
45
+
46
+ /*
47
+ * Macros
48
+ */
49
+
50
+ /*
51
+ * Types
52
+ */
53
+ namespace nm {
54
+
55
+ class RubyObject;
56
+ template <typename Type> class Complex;
57
+
58
+ typedef Complex<float32_t> Complex64;
59
+ typedef Complex<float64_t> Complex128;
60
+
61
+ /*
62
+ * Data
63
+ */
64
+
65
+ /*
66
+ * Classes and Functions
67
+ */
68
+
69
+ template <typename Type>
70
+ class Complex {
71
+ public:
72
+ // The real and immaginary parts of the complex number.
73
+ Type r;
74
+ Type i;
75
+
76
+ /*
77
+ * Default constructor.
78
+ */
79
+ inline Complex(Type real = 0, Type imaginary = 0) : r(real), i(imaginary) {}
80
+
81
+ /*
82
+ * Copy constructors.
83
+ */
84
+ template <typename ComplexType>
85
+ explicit inline Complex(const Complex<ComplexType>& other) : r(other.r), i(other.i) {}
86
+
87
+ template <typename ComplexType>
88
+ inline Complex<Type>& operator=(const Complex<ComplexType>& other) {
89
+ this->r = static_cast<Type>(other.r);
90
+ this->i = static_cast<Type>(other.i);
91
+ return *this;
92
+ }
93
+
94
+ explicit Complex(const RubyObject& other);
95
+
96
+ Complex<Type>& operator=(const RubyObject& other);
97
+
98
+ template<typename OtherType>
99
+ inline Complex<Type>& operator=(const OtherType& real) {
100
+ this->r = Type(real);
101
+ this->i = Type(0);
102
+ return *this;
103
+ }
104
+
105
+ /*
106
+ * Complex conjugate function -- creates a copy, but inverted.
107
+ */
108
+ inline Complex<Type> conjugate() const {
109
+ return Complex<Type>(this->r, -(this->i));
110
+ }
111
+
112
+ /*
113
+ * Complex inverse function -- creates a copy, but inverted.
114
+ *
115
+ * FIXME: Check that this doesn't duplicate functionality of NativeType / Complex<Type>
116
+ */
117
+ inline Complex<Type> inverse() const {
118
+ Complex<Type> conj = conjugate();
119
+ Type denom = this->r * this->r + this->i * this->i;
120
+ return Complex<Type>(conj.r / denom, conj.i / denom);
121
+ }
122
+
123
+ // Negative operator
124
+ inline Complex<Type> operator-() const {
125
+ return Complex<Type>(-this->r, -this->i);
126
+ }
127
+
128
+
129
+
130
+ /*
131
+ * Binary operator definitions for various types.
132
+ */
133
+
134
+ ////////////////////////////////
135
+ // Complex-Complex Operations //
136
+ ////////////////////////////////
137
+
138
+ template <typename OtherType>
139
+ inline Complex<Type> operator+(const Complex<OtherType>& other) const {
140
+ return Complex<Type>(this->r + other.r, this->i + other.i);
141
+ }
142
+
143
+ template <typename OtherType>
144
+ inline Complex<Type>& operator+=(const Complex<OtherType>& other) {
145
+ this->r += other.r;
146
+ this->i += other.i;
147
+ return *this;
148
+ }
149
+
150
+ template <typename OtherType>
151
+ inline Complex<Type>& operator-=(const Complex<OtherType>& other) {
152
+ this->r -= other.r;
153
+ this->i -= other.i;
154
+ return *this;
155
+ }
156
+
157
+ template <typename OtherType>
158
+ inline Complex<Type> operator-(const Complex<OtherType>& other) const {
159
+ return Complex<Type>(this->r - other.r, this->i - other.i);
160
+ }
161
+
162
+ template <typename OtherType>
163
+ inline Complex<Type> operator*(const Complex<OtherType>& other) const {
164
+ return Complex<Type>(this->r * other.r - this->i * other.i, this->r * other.i + this->i * other.r);
165
+ }
166
+
167
+ template <typename OtherType>
168
+ inline Complex<Type>& operator*=(const Complex<OtherType>& other) {
169
+ this->r = this->r * other.r - this->i * other.i;
170
+ this->i = this->r * other.i + this->i * other.r;
171
+ return *this;
172
+ }
173
+
174
+ template <typename OtherType>
175
+ inline Complex<Type> operator/(const Complex<OtherType>& other) const {
176
+ Type new_r, new_i;
177
+ Type denom = other.i * other.i + other.r * other.r;
178
+
179
+ new_r = (this->r * other.r + this->i * other.i) / denom;
180
+ new_i = (this->i * other.r - this->r * other.i) / denom;
181
+
182
+ return Complex<Type>(new_r, new_i);
183
+ }
184
+
185
+ template <typename OtherType>
186
+ inline Complex<Type> operator/=(const Complex<OtherType>& other) {
187
+ Type new_r, new_i;
188
+ Type denom = other.i * other.i + other.r * other.r;
189
+
190
+ new_r = (this->r * other.r + this->i * other.i) / denom;
191
+ new_i = (this->i * other.r - this->r * other.i) / denom;
192
+
193
+ this->r = new_r;
194
+ this->i = new_i;
195
+ return *this;
196
+ }
197
+
198
+ template <typename OtherType>
199
+ inline bool operator<(const Complex<OtherType>& other) const {
200
+ return (this->r < other.r) || ((this->r <= other.r) && (this->i < other.i));
201
+ }
202
+
203
+ template <typename OtherType>
204
+ inline bool operator>(const Complex<OtherType>& other) const {
205
+ return (this->r > other.r) || ((this->r >= other.r) && (this->i > other.i));
206
+ }
207
+
208
+ template <typename OtherType>
209
+ inline bool operator==(const Complex<OtherType>& other) const {
210
+ return FP_EQUAL(this->r, other.r) && FP_EQUAL(this->i, other.i);
211
+ }
212
+
213
+ template <typename OtherType>
214
+ inline bool operator!=(const Complex<OtherType>& other) const {
215
+ return !(*this == other);
216
+ }
217
+
218
+ template <typename OtherType>
219
+ inline bool operator<=(const Complex<OtherType>& other) const {
220
+ return (*this < other) || (*this == other);
221
+ }
222
+
223
+ template <typename OtherType>
224
+ inline bool operator>=(const Complex<OtherType>& other) const {
225
+ return (*this > other) || (*this == other);
226
+ }
227
+
228
+ template <typename OtherType>
229
+ inline operator Complex<OtherType> () const {
230
+ return Complex<OtherType>((OtherType)this->r, (OtherType)this->i);
231
+ }
232
+
233
+ ///////////////////////////////
234
+ // Complex-Native Operations //
235
+ ///////////////////////////////
236
+
237
+ template <typename NativeType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
238
+ inline Complex<Type> operator+(const NativeType& other) const {
239
+ return *this + Complex<Type>(other);
240
+ }
241
+
242
+ template <typename NativeType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
243
+ inline Complex<Type> operator-(const NativeType& other) const {
244
+ return *this - Complex<Type>(other);
245
+ }
246
+
247
+ template <typename NativeType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
248
+ inline Complex<Type> operator*(const NativeType& other) const {
249
+ return *this * Complex<Type>(other);
250
+ }
251
+
252
+ template <typename NativeType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
253
+ inline Complex<Type> operator/(const NativeType& other) const {
254
+ return *this / Complex<Type>(other);
255
+ }
256
+
257
+ template <typename NativeType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
258
+ inline bool operator<(const NativeType& other) const {
259
+ return *this < Complex<Type>(other);
260
+ }
261
+
262
+ template <typename NativeType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
263
+ inline bool operator>(const NativeType& other) const {
264
+ return *this > Complex<Type>(other);
265
+ }
266
+
267
+ template <typename NativeType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
268
+ inline bool operator==(const NativeType& other) const {
269
+ return *this == Complex<Type>(other);
270
+ }
271
+
272
+ template <typename NativeType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
273
+ inline bool operator!=(const NativeType& other) const {
274
+ return *this != Complex<Type>(other);
275
+ }
276
+
277
+ template <typename NativeType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
278
+ inline bool operator<=(const NativeType& other) const {
279
+ return *this <= Complex<Type>(other);
280
+ }
281
+
282
+ template <typename NativeType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
283
+ inline bool operator>=(const NativeType& other) const {
284
+ return *this >= Complex<Type>(other);
285
+ }
286
+
287
+ template <typename NativeType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
288
+ inline operator NativeType () const {
289
+ return (NativeType)this->r;
290
+ }
291
+
292
+ operator RubyObject () const;
293
+ };
294
+
295
+ ///////////////////////////////
296
+ // Native-Complex Operations //
297
+ ///////////////////////////////
298
+
299
+ template <typename NativeType, typename ComplexType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
300
+ inline Complex<ComplexType> operator+(const NativeType& left, const Complex<ComplexType>& right) {
301
+ return Complex<ComplexType>(left) + right;
302
+ }
303
+
304
+ template <typename NativeType, typename ComplexType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
305
+ inline Complex<ComplexType> operator-(const NativeType& left, const Complex<ComplexType>& right) {
306
+ return Complex<ComplexType>(left) - right;
307
+ }
308
+
309
+ template <typename NativeType, typename ComplexType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
310
+ inline Complex<ComplexType> operator*(const NativeType& left, const Complex<ComplexType>& right) {
311
+ return Complex<ComplexType>(left) * right;
312
+ }
313
+
314
+ template <typename NativeType, typename ComplexType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
315
+ inline Complex<ComplexType> operator/(const NativeType& left, const Complex<ComplexType>& right) {
316
+ return Complex<ComplexType>(left) / right;
317
+ }
318
+
319
+ template <typename NativeType, typename ComplexType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
320
+ inline bool operator<(const NativeType left, const Complex<ComplexType>& right) {
321
+ return Complex<ComplexType>(left) < right;
322
+ }
323
+
324
+ template <typename NativeType, typename ComplexType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
325
+ inline bool operator>(const NativeType left, const Complex<ComplexType>& right) {
326
+ return Complex<ComplexType>(left) > right;
327
+ }
328
+
329
+ template <typename NativeType, typename ComplexType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
330
+ inline bool operator==(const NativeType left, const Complex<ComplexType>& right) {
331
+ return Complex<ComplexType>(left) == right;
332
+ }
333
+
334
+ template <typename NativeType, typename ComplexType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
335
+ inline bool operator!=(const NativeType left, const Complex<ComplexType>& right) {
336
+ return Complex<ComplexType>(left) != right;
337
+ }
338
+
339
+ template <typename NativeType, typename ComplexType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
340
+ inline bool operator<=(const NativeType left, const Complex<ComplexType>& right) {
341
+ return Complex<ComplexType>(left) <= right;
342
+ }
343
+
344
+ template <typename NativeType, typename ComplexType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
345
+ inline bool operator>=(const NativeType left, const Complex<ComplexType>& right) {
346
+ return Complex<ComplexType>(left) >= right;
347
+ }
348
+
349
+ template <typename Type>
350
+ inline std::ostream& operator<<(std::ostream& out, const Complex<Type>& rhs) {
351
+ out << "(" << rhs.r << "," << rhs.i << "i)" << std::flush;
352
+ return out;
353
+ }
354
+
355
+ // Negative operator
356
+ template <typename IntType, typename = typename std::enable_if<std::is_integral<IntType>::value>::type>
357
+ inline Complex<IntType> operator-(const Complex<IntType>& rhs) {
358
+ return Complex<IntType>(-rhs.r, -rhs.i);
359
+ }
360
+
361
+ } // end of namespace nm
362
+
363
+ namespace std {
364
+ template <typename FloatType, typename = typename std::enable_if<std::is_floating_point<FloatType>::value>::type>
365
+ nm::Complex<FloatType> piecewise_abs(const nm::Complex<FloatType>& value) {
366
+ return nm::Complex<FloatType>(value.r < 0 ? -value.r : value.r,
367
+ value.i < 0 ? -value.i : value.i);
368
+ }
369
+
370
+ template <typename FloatType, typename = typename std::enable_if<std::is_floating_point<FloatType>::value>::type>
371
+ nm::Complex<FloatType> real_abs(const nm::Complex<FloatType>& value) {
372
+ return nm::Complex<FloatType>(value.r < 0 ? -value.r : value.r,
373
+ value.i);
374
+ }
375
+
376
+ template <typename FloatType, typename = typename std::enable_if<std::is_floating_point<FloatType>::value>::type>
377
+ nm::Complex<FloatType> imag_abs(const nm::Complex<FloatType>& value) {
378
+ return nm::Complex<FloatType>(value.r,
379
+ value.i < 0 ? -value.i : value.i);
380
+ }
381
+
382
+ template <typename FloatType, typename = typename std::enable_if<std::is_floating_point<FloatType>::value>::type>
383
+ double abs(const nm::Complex<FloatType>& value) {
384
+ return std::sqrt(double(value.r)*double(value.r) + double(value.i)*double(value.i));
385
+ }
386
+ }
387
+
388
+ #endif // COMPLEX_H