nmatrix-lapacke 0.2.1 → 0.2.3

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 (49) hide show
  1. checksums.yaml +4 -4
  2. data/ext/nmatrix/data/data.h +7 -8
  3. data/ext/nmatrix/data/ruby_object.h +1 -4
  4. data/ext/nmatrix/math/asum.h +10 -31
  5. data/ext/nmatrix/math/cblas_templates_core.h +10 -10
  6. data/ext/nmatrix/math/getrf.h +2 -2
  7. data/ext/nmatrix/math/imax.h +12 -9
  8. data/ext/nmatrix/math/laswp.h +3 -3
  9. data/ext/nmatrix/math/long_dtype.h +16 -3
  10. data/ext/nmatrix/math/magnitude.h +54 -0
  11. data/ext/nmatrix/math/nrm2.h +19 -14
  12. data/ext/nmatrix/math/trsm.h +40 -36
  13. data/ext/nmatrix/math/util.h +14 -0
  14. data/ext/nmatrix/nmatrix.h +39 -1
  15. data/ext/nmatrix/storage/common.h +9 -3
  16. data/ext/nmatrix/storage/yale/class.h +1 -1
  17. data/ext/nmatrix_lapacke/extconf.rb +3 -136
  18. data/ext/nmatrix_lapacke/lapacke.cpp +104 -84
  19. data/ext/nmatrix_lapacke/lapacke/src/lapacke_cgeqrf.c +77 -0
  20. data/ext/nmatrix_lapacke/lapacke/src/lapacke_cgeqrf_work.c +89 -0
  21. data/ext/nmatrix_lapacke/lapacke/src/lapacke_cunmqr.c +88 -0
  22. data/ext/nmatrix_lapacke/lapacke/src/lapacke_cunmqr_work.c +111 -0
  23. data/ext/nmatrix_lapacke/lapacke/src/lapacke_dgeqrf.c +75 -0
  24. data/ext/nmatrix_lapacke/lapacke/src/lapacke_dgeqrf_work.c +87 -0
  25. data/ext/nmatrix_lapacke/lapacke/src/lapacke_dormqr.c +86 -0
  26. data/ext/nmatrix_lapacke/lapacke/src/lapacke_dormqr_work.c +109 -0
  27. data/ext/nmatrix_lapacke/lapacke/src/lapacke_sgeqrf.c +75 -0
  28. data/ext/nmatrix_lapacke/lapacke/src/lapacke_sgeqrf_work.c +87 -0
  29. data/ext/nmatrix_lapacke/lapacke/src/lapacke_sormqr.c +86 -0
  30. data/ext/nmatrix_lapacke/lapacke/src/lapacke_sormqr_work.c +109 -0
  31. data/ext/nmatrix_lapacke/lapacke/src/lapacke_zgeqrf.c +77 -0
  32. data/ext/nmatrix_lapacke/lapacke/src/lapacke_zgeqrf_work.c +89 -0
  33. data/ext/nmatrix_lapacke/lapacke/src/lapacke_zunmqr.c +88 -0
  34. data/ext/nmatrix_lapacke/lapacke/src/lapacke_zunmqr_work.c +111 -0
  35. data/ext/nmatrix_lapacke/lapacke/utils/lapacke_c_nancheck.c +51 -0
  36. data/ext/nmatrix_lapacke/lapacke/utils/lapacke_d_nancheck.c +51 -0
  37. data/ext/nmatrix_lapacke/lapacke/utils/lapacke_s_nancheck.c +51 -0
  38. data/ext/nmatrix_lapacke/lapacke/utils/lapacke_z_nancheck.c +51 -0
  39. data/ext/nmatrix_lapacke/math_lapacke.cpp +149 -17
  40. data/ext/nmatrix_lapacke/math_lapacke/lapacke_templates.h +76 -0
  41. data/lib/nmatrix/lapacke.rb +118 -0
  42. data/spec/00_nmatrix_spec.rb +50 -1
  43. data/spec/02_slice_spec.rb +21 -21
  44. data/spec/blas_spec.rb +25 -3
  45. data/spec/math_spec.rb +233 -5
  46. data/spec/plugins/lapacke/lapacke_spec.rb +187 -0
  47. data/spec/shortcuts_spec.rb +145 -5
  48. data/spec/spec_helper.rb +24 -1
  49. metadata +38 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: eb2bd35041ab2a318db38bc9d91fb399ed239a78
4
- data.tar.gz: 847ccaae732e318cdf5bbf04a6419532bf5244b9
3
+ metadata.gz: 24925aa4dcfc784adc3fd27fa05687c0779d57e4
4
+ data.tar.gz: e0d5107e1d0211a1d32429e05a32ae1eb309c3bc
5
5
  SHA512:
6
- metadata.gz: a3835ad07419160226e85b9c5e2b47946ea4243d0b4a75a248e8334697969ac556a31c54dd6a4650ede2c6e9a301108c2ab7543c428eded3383e8e19c220460b
7
- data.tar.gz: cfb08870d965f5ef7cbbc83522ca6aed084992c1f828931a93600ebc6af53d432e61d8a3ffaf7a25461a29c6e7bc8efdd15ed7de9ce79efea53d72f867db8949
6
+ metadata.gz: 4be4b9ae38fe6cc8a2817ac79bf55a4541dd70708d0e86737c3179bd25d177b8bfb178d69ddc2a95396eac5d992bf40ae6f8b47554877c6657d8136e6bbe93df
7
+ data.tar.gz: 3cd253933d42d5a32780f717269b63583c489469d0d29bd8476fef61e5ed3ebb65c24ba5be5db36a38845ec3d60dbc3d3138fc1c0762a2e70890ede43262c8d5
@@ -121,18 +121,17 @@ namespace nm {
121
121
 
122
122
  template <typename Type>
123
123
  Complex<Type>& Complex<Type>::operator=(const RubyObject& other) {
124
- switch(TYPE(other.rval)) {
125
- case T_COMPLEX:
124
+ if (RB_TYPE_P(other.rval, T_COMPLEX)) {
126
125
  this->r = NUM2DBL(rb_funcall(other.rval, rb_intern("real"), 0));
127
126
  this->i = NUM2DBL(rb_funcall(other.rval, rb_intern("imag"), 0));
128
- break;
129
- case T_FLOAT:
130
- case T_FIXNUM:
131
- case T_BIGNUM:
127
+ }
128
+ else if (RB_TYPE_P(other.rval, T_FLOAT) ||
129
+ RB_TYPE_P(other.rval, T_FIXNUM) ||
130
+ RB_TYPE_P(other.rval, T_BIGNUM)) {
132
131
  this->r = NUM2DBL(other.rval);
133
132
  this->i = 0.0;
134
- break;
135
- default:
133
+ }
134
+ else {
136
135
  rb_raise(rb_eTypeError, "not sure how to convert this type of VALUE to a complex");
137
136
  }
138
137
  return *this;
@@ -45,10 +45,7 @@
45
45
  /*
46
46
  * Macros
47
47
  */
48
- #define NM_RUBYVAL_IS_NUMERIC(val) (FIXNUM_P(val) or (TYPE(val) == T_FLOAT) or (TYPE(val) == T_COMPLEX))
49
- #define NMATRIX_CHECK_TYPE(val) \
50
- if (TYPE(val) != T_DATA || (RDATA(val)->dfree != (RUBY_DATA_FUNC)nm_delete && RDATA(val)->dfree != (RUBY_DATA_FUNC)nm_delete_ref)) \
51
- rb_raise(rb_eTypeError, "Expected NMatrix on left-hand side of operation.");
48
+ #define NM_RUBYVAL_IS_NUMERIC(val) (FIXNUM_P(val) or RB_FLOAT_TYPE_P(val) or RB_TYPE_P(val, T_COMPLEX))
52
49
 
53
50
  /*
54
51
  * Classes and Functions
@@ -9,8 +9,8 @@
9
9
  //
10
10
  // == Copyright Information
11
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
12
+ // SciRuby is Copyright (c) 2010 - present, Ruby Science Foundation
13
+ // NMatrix is Copyright (c) 2012 - present, John Woods and the Ruby Science Foundation
14
14
  //
15
15
  // Please see LICENSE.txt for additional copyright notices.
16
16
  //
@@ -60,6 +60,8 @@
60
60
  #define ASUM_H
61
61
 
62
62
 
63
+ #include "math/magnitude.h"
64
+
63
65
  namespace nm { namespace math {
64
66
 
65
67
  /*
@@ -73,44 +75,21 @@ namespace nm { namespace math {
73
75
  * complex64 -> float or double
74
76
  * complex128 -> double
75
77
  */
76
- template <typename ReturnDType, typename DType>
77
- inline ReturnDType asum(const int N, const DType* X, const int incX) {
78
- ReturnDType sum = 0;
79
- if ((N > 0) && (incX > 0)) {
80
- for (int i = 0; i < N; ++i) {
81
- sum += std::abs(X[i*incX]);
82
- }
83
- }
84
- return sum;
85
- }
86
-
87
-
88
- template <>
89
- inline float asum(const int N, const Complex64* X, const int incX) {
90
- float sum = 0;
91
- if ((N > 0) && (incX > 0)) {
92
- for (int i = 0; i < N; ++i) {
93
- sum += std::abs(X[i*incX].r) + std::abs(X[i*incX].i);
94
- }
95
- }
96
- return sum;
97
- }
98
-
99
- template <>
100
- inline double asum(const int N, const Complex128* X, const int incX) {
101
- double sum = 0;
78
+ template <typename DType, typename MDType = typename MagnitudeDType<DType>::type>
79
+ inline MDType asum(const int N, const DType* X, const int incX) {
80
+ MDType sum = 0;
102
81
  if ((N > 0) && (incX > 0)) {
103
82
  for (int i = 0; i < N; ++i) {
104
- sum += std::abs(X[i*incX].r) + std::abs(X[i*incX].i);
83
+ sum += magnitude(X[i*incX]);
105
84
  }
106
85
  }
107
86
  return sum;
108
87
  }
109
88
 
110
89
 
111
- template <typename ReturnDType, typename DType>
90
+ template <typename DType, typename MDType = typename MagnitudeDType<DType>::type>
112
91
  inline void cblas_asum(const int N, const void* X, const int incX, void* sum) {
113
- *reinterpret_cast<ReturnDType*>( sum ) = asum<ReturnDType, DType>( N, reinterpret_cast<const DType*>(X), incX );
92
+ *reinterpret_cast<MDType*>( sum ) = asum<DType,MDType>( N, reinterpret_cast<const DType*>(X), incX );
114
93
  }
115
94
 
116
95
 
@@ -107,9 +107,9 @@ inline void cblas_rot(const int N, void* X, const int incX, void* Y, const int i
107
107
  * complex64 -> float or double
108
108
  * complex128 -> double
109
109
  */
110
- template <typename ReturnDType, typename DType>
111
- inline ReturnDType asum(const int N, const DType* X, const int incX) {
112
- return nm::math::asum<ReturnDType,DType>(N,X,incX);
110
+ template <typename DType, typename MDType = typename MagnitudeDType<DType>::type>
111
+ inline MDType asum(const int N, const DType* X, const int incX) {
112
+ return nm::math::asum<DType,MDType>(N,X,incX);
113
113
  }
114
114
 
115
115
 
@@ -134,9 +134,9 @@ inline double asum(const int N, const Complex128* X, const int incX) {
134
134
  }
135
135
 
136
136
 
137
- template <typename ReturnDType, typename DType>
137
+ template <typename DType, typename MDType = typename MagnitudeDType<DType>::type>
138
138
  inline void cblas_asum(const int N, const void* X, const int incX, void* sum) {
139
- *static_cast<ReturnDType*>( sum ) = asum<ReturnDType, DType>( N, static_cast<const DType*>(X), incX );
139
+ *static_cast<MDType*>( sum ) = asum<DType, MDType>( N, static_cast<const DType*>(X), incX );
140
140
  }
141
141
 
142
142
  /*
@@ -149,9 +149,9 @@ inline void cblas_asum(const int N, const void* X, const int incX, void* sum) {
149
149
  * complex64 -> float or double
150
150
  * complex128 -> double
151
151
  */
152
- template <typename ReturnDType, typename DType>
153
- inline ReturnDType nrm2(const int N, const DType* X, const int incX) {
154
- return nm::math::nrm2<ReturnDType,DType>(N, X, incX);
152
+ template <typename DType, typename MDType = typename MagnitudeDType<DType>::type>
153
+ inline MDType nrm2(const int N, const DType* X, const int incX) {
154
+ return nm::math::nrm2<DType,MDType>(N, X, incX);
155
155
  }
156
156
 
157
157
 
@@ -175,9 +175,9 @@ inline double nrm2(const int N, const Complex128* X, const int incX) {
175
175
  return cblas_dznrm2(N, X, incX);
176
176
  }
177
177
 
178
- template <typename ReturnDType, typename DType>
178
+ template <typename DType, typename MDType = typename MagnitudeDType<DType>::type>
179
179
  inline void cblas_nrm2(const int N, const void* X, const int incX, void* result) {
180
- *static_cast<ReturnDType*>( result ) = nrm2<ReturnDType, DType>( N, static_cast<const DType*>(X), incX );
180
+ *static_cast<MDType*>( result ) = nrm2<DType, MDType>( N, static_cast<const DType*>(X), incX );
181
181
  }
182
182
 
183
183
  //imax
@@ -9,8 +9,8 @@
9
9
  //
10
10
  // == Copyright Information
11
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
12
+ // SciRuby is Copyright (c) 2010 - present, Ruby Science Foundation
13
+ // NMatrix is Copyright (c) 2012 - present, John Woods and the Ruby Science Foundation
14
14
  //
15
15
  // Please see LICENSE.txt for additional copyright notices.
16
16
  //
@@ -9,8 +9,8 @@
9
9
  //
10
10
  // == Copyright Information
11
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
12
+ // SciRuby is Copyright (c) 2010 - present, Ruby Science Foundation
13
+ // NMatrix is Copyright (c) 2012 - present, John Woods and the Ruby Science Foundation
14
14
  //
15
15
  // Please see LICENSE.txt for additional copyright notices.
16
16
  //
@@ -29,8 +29,11 @@
29
29
  #ifndef IMAX_H
30
30
  #define IMAX_H
31
31
 
32
+ #include "math/magnitude.h"
33
+
32
34
  namespace nm { namespace math {
33
35
 
36
+
34
37
  template<typename DType>
35
38
  inline int imax(const int n, const DType *x, const int incx) {
36
39
 
@@ -41,28 +44,28 @@ inline int imax(const int n, const DType *x, const int incx) {
41
44
  return 0;
42
45
  }
43
46
 
44
- DType dmax;
47
+ typename MagnitudeDType<DType>::type dmax;
45
48
  int imax = 0;
46
49
 
47
50
  if (incx == 1) { // if incrementing by 1
48
51
 
49
- dmax = abs(x[0]);
52
+ dmax = magnitude(x[0]);
50
53
 
51
54
  for (int i = 1; i < n; ++i) {
52
- if (std::abs(x[i]) > dmax) {
55
+ if (magnitude(x[i]) > dmax) {
53
56
  imax = i;
54
- dmax = std::abs(x[i]);
57
+ dmax = magnitude(x[i]);
55
58
  }
56
59
  }
57
60
 
58
61
  } else { // if incrementing by more than 1
59
62
 
60
- dmax = std::abs(x[0]);
63
+ dmax = magnitude(x[0]);
61
64
 
62
65
  for (int i = 1, ix = incx; i < n; ++i, ix += incx) {
63
- if (std::abs(x[ix]) > dmax) {
66
+ if (magnitude(x[ix]) > dmax) {
64
67
  imax = i;
65
- dmax = std::abs(x[ix]);
68
+ dmax = magnitude(x[ix]);
66
69
  }
67
70
  }
68
71
  }
@@ -102,7 +102,7 @@ inline void laswp(const int N, DType* A, const int lda, const int K1, const int
102
102
  DType *a0 = &(A[i]),
103
103
  *a1 = &(A[ip]);
104
104
 
105
- for (register int h = 32; h; h--) {
105
+ for (int h = 32; h; h--) {
106
106
  DType r = *a0;
107
107
  *a0 = *a1;
108
108
  *a1 = r;
@@ -131,7 +131,7 @@ inline void laswp(const int N, DType* A, const int lda, const int K1, const int
131
131
  DType *a0 = &(A[i]),
132
132
  *a1 = &(A[ip]);
133
133
 
134
- for (register int h = mr; h; h--) {
134
+ for (int h = mr; h; h--) {
135
135
  DType r = *a0;
136
136
  *a0 = *a1;
137
137
  *a1 = r;
@@ -162,4 +162,4 @@ inline void clapack_laswp(const int n, void* a, const int lda, const int k1, con
162
162
  }
163
163
 
164
164
  } } // namespace nm::math
165
- #endif // LASWP_H
165
+ #endif // LASWP_H
@@ -9,8 +9,8 @@
9
9
  //
10
10
  // == Copyright Information
11
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
12
+ // SciRuby is Copyright (c) 2010 - present, Ruby Science Foundation
13
+ // NMatrix is Copyright (c) 2012 - present, John Woods and the Ruby Science Foundation
14
14
  //
15
15
  // Please see LICENSE.txt for additional copyright notices.
16
16
  //
@@ -23,7 +23,8 @@
23
23
  //
24
24
  // == long_dtype.h
25
25
  //
26
- // Declarations necessary for the native versions of GEMM and GEMV.
26
+ // Declarations necessary for the native versions of GEMM and GEMV,
27
+ // as well as for IMAX.
27
28
  //
28
29
 
29
30
  #ifndef LONG_DTYPE_H
@@ -44,6 +45,18 @@ namespace nm { namespace math {
44
45
  template <> struct LongDType<Complex128> { typedef Complex128 type; };
45
46
  template <> struct LongDType<RubyObject> { typedef RubyObject type; };
46
47
 
48
+ template <typename DType> struct MagnitudeDType;
49
+ template <> struct MagnitudeDType<uint8_t> { typedef uint8_t type; };
50
+ template <> struct MagnitudeDType<int8_t> { typedef int8_t type; };
51
+ template <> struct MagnitudeDType<int16_t> { typedef int16_t type; };
52
+ template <> struct MagnitudeDType<int32_t> { typedef int32_t type; };
53
+ template <> struct MagnitudeDType<int64_t> { typedef int64_t type; };
54
+ template <> struct MagnitudeDType<float> { typedef float type; };
55
+ template <> struct MagnitudeDType<double> { typedef double type; };
56
+ template <> struct MagnitudeDType<Complex64> { typedef float type; };
57
+ template <> struct MagnitudeDType<Complex128> { typedef double type; };
58
+ template <> struct MagnitudeDType<RubyObject> { typedef RubyObject type; };
59
+
47
60
  }} // end of namespace nm::math
48
61
 
49
62
  #endif
@@ -0,0 +1,54 @@
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 - present, Ruby Science Foundation
13
+ // NMatrix is Copyright (c) 2012 - present, 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
+ // == math/magnitude.h
25
+ //
26
+ // Takes the absolute value (meaning magnitude) of each DType.
27
+ // Needed for a variety of BLAS/LAPACK functions.
28
+ //
29
+
30
+ #ifndef MAGNITUDE_H
31
+ #define MAGNITUDE_H
32
+
33
+ #include "math/long_dtype.h"
34
+
35
+ namespace nm { namespace math {
36
+
37
+ /* Magnitude -- may be complicated for unsigned types, and need to call the correct STL abs for floats/doubles */
38
+ template <typename DType, typename MDType = typename MagnitudeDType<DType>::type>
39
+ inline MDType magnitude(const DType& v) {
40
+ return v.abs();
41
+ }
42
+ template <> inline float magnitude(const float& v) { return std::abs(v); }
43
+ template <> inline double magnitude(const double& v) { return std::abs(v); }
44
+ template <> inline uint8_t magnitude(const uint8_t& v) { return v; }
45
+ template <> inline int8_t magnitude(const int8_t& v) { return std::abs(v); }
46
+ template <> inline int16_t magnitude(const int16_t& v) { return std::abs(v); }
47
+ template <> inline int32_t magnitude(const int32_t& v) { return std::abs(v); }
48
+ template <> inline int64_t magnitude(const int64_t& v) { return std::abs(v); }
49
+ template <> inline float magnitude(const nm::Complex64& v) { return std::sqrt(v.r * v.r + v.i * v.i); }
50
+ template <> inline double magnitude(const nm::Complex128& v) { return std::sqrt(v.r * v.r + v.i * v.i); }
51
+
52
+ }}
53
+
54
+ #endif // MAGNITUDE_H
@@ -9,8 +9,8 @@
9
9
  //
10
10
  // == Copyright Information
11
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
12
+ // SciRuby is Copyright (c) 2010 - present, Ruby Science Foundation
13
+ // NMatrix is Copyright (c) 2012 - present, John Woods and the Ruby Science Foundation
14
14
  //
15
15
  // Please see LICENSE.txt for additional copyright notices.
16
16
  //
@@ -74,8 +74,8 @@ namespace nm { namespace math {
74
74
  * complex64 -> float or double
75
75
  * complex128 -> double
76
76
  */
77
- template <typename ReturnDType, typename DType>
78
- ReturnDType nrm2(const int N, const DType* X, const int incX) {
77
+ template <typename DType, typename MDType = typename MagnitudeDType<DType>::type>
78
+ MDType nrm2(const int N, const DType* X, const int incX) {
79
79
  const DType ONE = 1, ZERO = 0;
80
80
  typename LongDType<DType>::type scale = 0, ssq = 1, absxi, temp;
81
81
 
@@ -89,13 +89,14 @@ ReturnDType nrm2(const int N, const DType* X, const int incX) {
89
89
  temp = scale / absxi;
90
90
  scale = absxi;
91
91
  ssq = ONE + ssq * (temp * temp);
92
- } else {
92
+ }
93
+ else if(scale != 0) {
93
94
  temp = absxi / scale;
94
95
  ssq += temp * temp;
95
96
  }
96
97
  }
97
98
 
98
- return scale * std::sqrt( ssq );
99
+ return (MDType)(scale * std::sqrt( ssq ));
99
100
  }
100
101
 
101
102
 
@@ -106,7 +107,8 @@ static inline void nrm2_complex_helper(const FloatDType& xr, const FloatDType& x
106
107
  double temp = scale / absx;
107
108
  scale = absx;
108
109
  ssq = 1.0 + ssq * (temp * temp);
109
- } else {
110
+ }
111
+ else if(scale != 0) {
110
112
  double temp = absx / scale;
111
113
  ssq += temp * temp;
112
114
  }
@@ -116,7 +118,8 @@ static inline void nrm2_complex_helper(const FloatDType& xr, const FloatDType& x
116
118
  double temp = scale / absx;
117
119
  scale = absx;
118
120
  ssq = 1.0 + ssq * (temp * temp);
119
- } else {
121
+ }
122
+ else if(scale != 0) {
120
123
  double temp = absx / scale;
121
124
  ssq += temp * temp;
122
125
  }
@@ -124,33 +127,35 @@ static inline void nrm2_complex_helper(const FloatDType& xr, const FloatDType& x
124
127
 
125
128
  template <>
126
129
  float nrm2(const int N, const Complex64* X, const int incX) {
127
- double scale = 0, ssq = 1, temp;
130
+ double scale = 0, ssq = 1;
128
131
 
129
132
  if ((N < 1) || (incX < 1)) return 0.0;
130
133
 
131
134
  for (int i = 0; i < N; ++i) {
132
- nrm2_complex_helper<float>(X[i*incX].r, X[i*incX].i, scale, temp);
135
+ nrm2_complex_helper<float>(X[i*incX].r, X[i*incX].i, scale, ssq);
133
136
  }
134
137
 
135
138
  return scale * std::sqrt( ssq );
136
139
  }
137
140
 
141
+ // FIXME: Function above is duplicated here, should be writeable as a template using
142
+ // FIXME: xMagnitudeDType.
138
143
  template <>
139
144
  double nrm2(const int N, const Complex128* X, const int incX) {
140
- double scale = 0, ssq = 1, temp;
145
+ double scale = 0, ssq = 1;
141
146
 
142
147
  if ((N < 1) || (incX < 1)) return 0.0;
143
148
 
144
149
  for (int i = 0; i < N; ++i) {
145
- nrm2_complex_helper<double>(X[i*incX].r, X[i*incX].i, scale, temp);
150
+ nrm2_complex_helper<double>(X[i*incX].r, X[i*incX].i, scale, ssq);
146
151
  }
147
152
 
148
153
  return scale * std::sqrt( ssq );
149
154
  }
150
155
 
151
- template <typename ReturnDType, typename DType>
156
+ template <typename DType, typename MDType = typename MagnitudeDType<DType>::type>
152
157
  inline void cblas_nrm2(const int N, const void* X, const int incX, void* result) {
153
- *reinterpret_cast<ReturnDType*>( result ) = nrm2<ReturnDType, DType>( N, reinterpret_cast<const DType*>(X), incX );
158
+ *reinterpret_cast<MDType*>( result ) = nrm2<DType, MDType>( N, reinterpret_cast<const DType*>(X), incX );
154
159
  }
155
160
 
156
161