numo-linalg-alt 0.3.0 → 0.4.0

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 (53) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/ext/numo/linalg/blas/dot.c +59 -59
  4. data/ext/numo/linalg/blas/dot_sub.c +58 -58
  5. data/ext/numo/linalg/blas/gemm.c +157 -148
  6. data/ext/numo/linalg/blas/gemv.c +131 -127
  7. data/ext/numo/linalg/blas/nrm2.c +50 -50
  8. data/ext/numo/linalg/lapack/gees.c +239 -220
  9. data/ext/numo/linalg/lapack/geev.c +127 -110
  10. data/ext/numo/linalg/lapack/gelsd.c +81 -70
  11. data/ext/numo/linalg/lapack/geqrf.c +52 -51
  12. data/ext/numo/linalg/lapack/gerqf.c +70 -0
  13. data/ext/numo/linalg/lapack/gerqf.h +15 -0
  14. data/ext/numo/linalg/lapack/gesdd.c +96 -86
  15. data/ext/numo/linalg/lapack/gesv.c +80 -78
  16. data/ext/numo/linalg/lapack/gesvd.c +140 -129
  17. data/ext/numo/linalg/lapack/getrf.c +51 -50
  18. data/ext/numo/linalg/lapack/getri.c +64 -63
  19. data/ext/numo/linalg/lapack/getrs.c +92 -88
  20. data/ext/numo/linalg/lapack/gges.c +214 -0
  21. data/ext/numo/linalg/lapack/gges.h +15 -0
  22. data/ext/numo/linalg/lapack/heev.c +54 -52
  23. data/ext/numo/linalg/lapack/heevd.c +54 -52
  24. data/ext/numo/linalg/lapack/heevr.c +109 -98
  25. data/ext/numo/linalg/lapack/hegv.c +77 -74
  26. data/ext/numo/linalg/lapack/hegvd.c +77 -74
  27. data/ext/numo/linalg/lapack/hegvx.c +132 -120
  28. data/ext/numo/linalg/lapack/hetrf.c +54 -50
  29. data/ext/numo/linalg/lapack/lange.c +45 -44
  30. data/ext/numo/linalg/lapack/orgqr.c +63 -62
  31. data/ext/numo/linalg/lapack/orgrq.c +78 -0
  32. data/ext/numo/linalg/lapack/orgrq.h +15 -0
  33. data/ext/numo/linalg/lapack/potrf.c +49 -48
  34. data/ext/numo/linalg/lapack/potri.c +49 -48
  35. data/ext/numo/linalg/lapack/potrs.c +74 -72
  36. data/ext/numo/linalg/lapack/syev.c +54 -52
  37. data/ext/numo/linalg/lapack/syevd.c +54 -52
  38. data/ext/numo/linalg/lapack/syevr.c +107 -98
  39. data/ext/numo/linalg/lapack/sygv.c +77 -73
  40. data/ext/numo/linalg/lapack/sygvd.c +77 -73
  41. data/ext/numo/linalg/lapack/sygvx.c +132 -120
  42. data/ext/numo/linalg/lapack/sytrf.c +54 -50
  43. data/ext/numo/linalg/lapack/trtrs.c +79 -75
  44. data/ext/numo/linalg/lapack/ungqr.c +63 -62
  45. data/ext/numo/linalg/lapack/ungrq.c +78 -0
  46. data/ext/numo/linalg/lapack/ungrq.h +15 -0
  47. data/ext/numo/linalg/linalg.c +20 -10
  48. data/ext/numo/linalg/linalg.h +4 -0
  49. data/ext/numo/linalg/util.c +8 -0
  50. data/ext/numo/linalg/util.h +1 -0
  51. data/lib/numo/linalg/version.rb +1 -1
  52. data/lib/numo/linalg.rb +139 -3
  53. metadata +10 -2
@@ -1,138 +1,142 @@
1
1
  #include "gemv.h"
2
2
 
3
- #define DEF_LINALG_OPTIONS(tDType) \
4
- struct _gemv_options_##tDType { \
5
- tDType alpha; \
6
- tDType beta; \
7
- enum CBLAS_ORDER order; \
8
- enum CBLAS_TRANSPOSE trans; \
9
- blasint m; \
10
- blasint n; \
3
+ #define DEF_LINALG_OPTIONS(tDType) \
4
+ struct _gemv_options_##tDType { \
5
+ tDType alpha; \
6
+ tDType beta; \
7
+ enum CBLAS_ORDER order; \
8
+ enum CBLAS_TRANSPOSE trans; \
9
+ blasint m; \
10
+ blasint n; \
11
11
  };
12
12
 
13
- #define DEF_LINALG_ITER_FUNC(tDType, fBlasFunc) \
14
- static void _iter_##fBlasFunc(na_loop_t* const lp) { \
15
- const tDType* a = (tDType*)NDL_PTR(lp, 0); \
16
- const tDType* x = (tDType*)NDL_PTR(lp, 1); \
17
- tDType* y = (tDType*)NDL_PTR(lp, 2); \
18
- const struct _gemv_options_##tDType* opt = (struct _gemv_options_##tDType*)(lp->opt_ptr); \
19
- const blasint lda = opt->n; \
20
- cblas_##fBlasFunc(opt->order, opt->trans, opt->m, opt->n, \
21
- opt->alpha, a, lda, x, 1, opt->beta, y, 1); \
13
+ #define DEF_LINALG_ITER_FUNC(tDType, fBlasFunc) \
14
+ static void _iter_##fBlasFunc(na_loop_t* const lp) { \
15
+ const tDType* a = (tDType*)NDL_PTR(lp, 0); \
16
+ const tDType* x = (tDType*)NDL_PTR(lp, 1); \
17
+ tDType* y = (tDType*)NDL_PTR(lp, 2); \
18
+ const struct _gemv_options_##tDType* opt = (struct _gemv_options_##tDType*)(lp->opt_ptr); \
19
+ const blasint lda = opt->n; \
20
+ cblas_##fBlasFunc( \
21
+ opt->order, opt->trans, opt->m, opt->n, opt->alpha, a, lda, x, 1, opt->beta, y, 1 \
22
+ ); \
22
23
  }
23
24
 
24
- #define DEF_LINALG_ITER_FUNC_COMPLEX(tDType, fBlasFunc) \
25
- static void _iter_##fBlasFunc(na_loop_t* const lp) { \
26
- const tDType* a = (tDType*)NDL_PTR(lp, 0); \
27
- const tDType* x = (tDType*)NDL_PTR(lp, 1); \
28
- tDType* y = (tDType*)NDL_PTR(lp, 2); \
29
- const struct _gemv_options_##tDType* opt = (struct _gemv_options_##tDType*)(lp->opt_ptr); \
30
- const blasint lda = opt->n; \
31
- cblas_##fBlasFunc(opt->order, opt->trans, opt->m, opt->n, \
32
- &opt->alpha, a, lda, x, 1, &opt->beta, y, 1); \
25
+ #define DEF_LINALG_ITER_FUNC_COMPLEX(tDType, fBlasFunc) \
26
+ static void _iter_##fBlasFunc(na_loop_t* const lp) { \
27
+ const tDType* a = (tDType*)NDL_PTR(lp, 0); \
28
+ const tDType* x = (tDType*)NDL_PTR(lp, 1); \
29
+ tDType* y = (tDType*)NDL_PTR(lp, 2); \
30
+ const struct _gemv_options_##tDType* opt = (struct _gemv_options_##tDType*)(lp->opt_ptr); \
31
+ const blasint lda = opt->n; \
32
+ cblas_##fBlasFunc( \
33
+ opt->order, opt->trans, opt->m, opt->n, &opt->alpha, a, lda, x, 1, &opt->beta, y, 1 \
34
+ ); \
33
35
  }
34
36
 
35
- #define DEF_LINALG_FUNC(tDType, tNAryClass, fBlasFunc) \
36
- static VALUE _linalg_blas_##fBlasFunc(int argc, VALUE* argv, VALUE self) { \
37
- VALUE a = Qnil; \
38
- VALUE x = Qnil; \
39
- VALUE y = Qnil; \
40
- VALUE kw_args = Qnil; \
41
- rb_scan_args(argc, argv, "21:", &a, &x, &y, &kw_args); \
42
- \
43
- ID kw_table[4] = { rb_intern("alpha"), rb_intern("beta"), \
44
- rb_intern("order"), rb_intern("trans") }; \
45
- VALUE kw_values[4] = { Qundef, Qundef, Qundef, Qundef }; \
46
- rb_get_kwargs(kw_args, kw_table, 0, 4, kw_values); \
47
- \
48
- if (CLASS_OF(a) != tNAryClass) { \
49
- a = rb_funcall(tNAryClass, rb_intern("cast"), 1, a); \
50
- } \
51
- if (!RTEST(nary_check_contiguous(a))) { \
52
- a = nary_dup(a); \
53
- } \
54
- if (CLASS_OF(x) != tNAryClass) { \
55
- x = rb_funcall(tNAryClass, rb_intern("cast"), 1, x); \
56
- } \
57
- if (!RTEST(nary_check_contiguous(x))) { \
58
- x = nary_dup(x); \
59
- } \
60
- if (!NIL_P(y)) { \
61
- if (CLASS_OF(y) != tNAryClass) { \
62
- y = rb_funcall(tNAryClass, rb_intern("cast"), 1, y); \
63
- } \
64
- if (!RTEST(nary_check_contiguous(y))) { \
65
- y = nary_dup(y); \
66
- } \
67
- } \
68
- \
69
- tDType alpha = kw_values[0] != Qundef ? conv_##tDType(kw_values[0]) : one_##tDType(); \
70
- tDType beta = kw_values[1] != Qundef ? conv_##tDType(kw_values[1]) : zero_##tDType(); \
71
- enum CBLAS_ORDER order = kw_values[2] != Qundef ? get_cblas_order(kw_values[2]) : CblasRowMajor; \
72
- enum CBLAS_TRANSPOSE trans = kw_values[3] != Qundef ? get_cblas_trans(kw_values[3]) : CblasNoTrans; \
73
- \
74
- narray_t* a_nary = NULL; \
75
- GetNArray(a, a_nary); \
76
- narray_t* x_nary = NULL; \
77
- GetNArray(x, x_nary); \
78
- \
79
- if (NA_NDIM(a_nary) != 2) { \
80
- rb_raise(rb_eArgError, "a must be 2-dimensional"); \
81
- return Qnil; \
82
- } \
83
- if (NA_NDIM(x_nary) != 1) { \
84
- rb_raise(rb_eArgError, "x must be 1-dimensional"); \
85
- return Qnil; \
86
- } \
87
- if (NA_SIZE(a_nary) == 0) { \
88
- rb_raise(rb_eArgError, "a must not be empty"); \
89
- return Qnil; \
90
- } \
91
- if (NA_SIZE(x_nary) == 0) { \
92
- rb_raise(rb_eArgError, "x must not be empty"); \
93
- return Qnil; \
94
- } \
95
- \
96
- const blasint ma = (blasint)NA_SHAPE(a_nary)[0]; \
97
- const blasint na = (blasint)NA_SHAPE(a_nary)[1]; \
98
- const blasint mx = (blasint)NA_SHAPE(x_nary)[0]; \
99
- const blasint m = trans == CblasNoTrans ? ma : na; \
100
- const blasint n = trans == CblasNoTrans ? na : ma; \
101
- \
102
- if (n != mx) { \
103
- rb_raise(nary_eShapeError, "shape1[1](=%d) != shape2[0](=%d)", n, mx); \
104
- return Qnil; \
105
- } \
106
- \
107
- struct _gemv_options_##tDType opt = { alpha, beta, order, trans, ma, na }; \
108
- size_t shape_out[1] = { (size_t)(m) }; \
109
- ndfunc_arg_out_t aout[1] = { { tNAryClass, 1, shape_out } }; \
110
- VALUE ret = Qnil; \
111
- \
112
- if (!NIL_P(y)) { \
113
- narray_t* y_nary = NULL; \
114
- GetNArray(y, y_nary); \
115
- blasint my = (blasint)NA_SHAPE(y_nary)[0]; \
116
- if (m > my) { \
117
- rb_raise(nary_eShapeError, "shape3[0](=%d) >= shape1[0]=%d", my, m); \
118
- return Qnil; \
119
- } \
120
- ndfunc_arg_in_t ain[3] = { { tNAryClass, 2 }, { tNAryClass, 1 }, { OVERWRITE, 1 } }; \
121
- ndfunc_t ndf = { _iter_##fBlasFunc, NO_LOOP, 3, 0, ain, aout }; \
122
- na_ndloop3(&ndf, &opt, 3, a, x, y); \
123
- ret = y; \
124
- } else { \
125
- y = INT2NUM(0); \
126
- ndfunc_arg_in_t ain[3] = { { tNAryClass, 2 }, { tNAryClass, 1 }, { sym_init, 0 } }; \
127
- ndfunc_t ndf = { _iter_##fBlasFunc, NO_LOOP, 3, 1, ain, aout }; \
128
- ret = na_ndloop3(&ndf, &opt, 3, a, x, y); \
129
- } \
130
- \
131
- RB_GC_GUARD(a); \
132
- RB_GC_GUARD(x); \
133
- RB_GC_GUARD(y); \
134
- \
135
- return ret; \
37
+ #define DEF_LINALG_FUNC(tDType, tNAryClass, fBlasFunc) \
38
+ static VALUE _linalg_blas_##fBlasFunc(int argc, VALUE* argv, VALUE self) { \
39
+ VALUE a = Qnil; \
40
+ VALUE x = Qnil; \
41
+ VALUE y = Qnil; \
42
+ VALUE kw_args = Qnil; \
43
+ rb_scan_args(argc, argv, "21:", &a, &x, &y, &kw_args); \
44
+ \
45
+ ID kw_table[4] = { rb_intern("alpha"), rb_intern("beta"), rb_intern("order"), \
46
+ rb_intern("trans") }; \
47
+ VALUE kw_values[4] = { Qundef, Qundef, Qundef, Qundef }; \
48
+ rb_get_kwargs(kw_args, kw_table, 0, 4, kw_values); \
49
+ \
50
+ if (CLASS_OF(a) != tNAryClass) { \
51
+ a = rb_funcall(tNAryClass, rb_intern("cast"), 1, a); \
52
+ } \
53
+ if (!RTEST(nary_check_contiguous(a))) { \
54
+ a = nary_dup(a); \
55
+ } \
56
+ if (CLASS_OF(x) != tNAryClass) { \
57
+ x = rb_funcall(tNAryClass, rb_intern("cast"), 1, x); \
58
+ } \
59
+ if (!RTEST(nary_check_contiguous(x))) { \
60
+ x = nary_dup(x); \
61
+ } \
62
+ if (!NIL_P(y)) { \
63
+ if (CLASS_OF(y) != tNAryClass) { \
64
+ y = rb_funcall(tNAryClass, rb_intern("cast"), 1, y); \
65
+ } \
66
+ if (!RTEST(nary_check_contiguous(y))) { \
67
+ y = nary_dup(y); \
68
+ } \
69
+ } \
70
+ \
71
+ tDType alpha = kw_values[0] != Qundef ? conv_##tDType(kw_values[0]) : one_##tDType(); \
72
+ tDType beta = kw_values[1] != Qundef ? conv_##tDType(kw_values[1]) : zero_##tDType(); \
73
+ enum CBLAS_ORDER order = \
74
+ kw_values[2] != Qundef ? get_cblas_order(kw_values[2]) : CblasRowMajor; \
75
+ enum CBLAS_TRANSPOSE trans = \
76
+ kw_values[3] != Qundef ? get_cblas_trans(kw_values[3]) : CblasNoTrans; \
77
+ \
78
+ narray_t* a_nary = NULL; \
79
+ GetNArray(a, a_nary); \
80
+ narray_t* x_nary = NULL; \
81
+ GetNArray(x, x_nary); \
82
+ \
83
+ if (NA_NDIM(a_nary) != 2) { \
84
+ rb_raise(rb_eArgError, "a must be 2-dimensional"); \
85
+ return Qnil; \
86
+ } \
87
+ if (NA_NDIM(x_nary) != 1) { \
88
+ rb_raise(rb_eArgError, "x must be 1-dimensional"); \
89
+ return Qnil; \
90
+ } \
91
+ if (NA_SIZE(a_nary) == 0) { \
92
+ rb_raise(rb_eArgError, "a must not be empty"); \
93
+ return Qnil; \
94
+ } \
95
+ if (NA_SIZE(x_nary) == 0) { \
96
+ rb_raise(rb_eArgError, "x must not be empty"); \
97
+ return Qnil; \
98
+ } \
99
+ \
100
+ const blasint ma = (blasint)NA_SHAPE(a_nary)[0]; \
101
+ const blasint na = (blasint)NA_SHAPE(a_nary)[1]; \
102
+ const blasint mx = (blasint)NA_SHAPE(x_nary)[0]; \
103
+ const blasint m = trans == CblasNoTrans ? ma : na; \
104
+ const blasint n = trans == CblasNoTrans ? na : ma; \
105
+ \
106
+ if (n != mx) { \
107
+ rb_raise(nary_eShapeError, "shape1[1](=%d) != shape2[0](=%d)", n, mx); \
108
+ return Qnil; \
109
+ } \
110
+ \
111
+ struct _gemv_options_##tDType opt = { alpha, beta, order, trans, ma, na }; \
112
+ size_t shape_out[1] = { (size_t)(m) }; \
113
+ ndfunc_arg_out_t aout[1] = { { tNAryClass, 1, shape_out } }; \
114
+ VALUE ret = Qnil; \
115
+ \
116
+ if (!NIL_P(y)) { \
117
+ narray_t* y_nary = NULL; \
118
+ GetNArray(y, y_nary); \
119
+ blasint my = (blasint)NA_SHAPE(y_nary)[0]; \
120
+ if (m > my) { \
121
+ rb_raise(nary_eShapeError, "shape3[0](=%d) >= shape1[0]=%d", my, m); \
122
+ return Qnil; \
123
+ } \
124
+ ndfunc_arg_in_t ain[3] = { { tNAryClass, 2 }, { tNAryClass, 1 }, { OVERWRITE, 1 } }; \
125
+ ndfunc_t ndf = { _iter_##fBlasFunc, NO_LOOP, 3, 0, ain, aout }; \
126
+ na_ndloop3(&ndf, &opt, 3, a, x, y); \
127
+ ret = y; \
128
+ } else { \
129
+ y = INT2NUM(0); \
130
+ ndfunc_arg_in_t ain[3] = { { tNAryClass, 2 }, { tNAryClass, 1 }, { sym_init, 0 } }; \
131
+ ndfunc_t ndf = { _iter_##fBlasFunc, NO_LOOP, 3, 1, ain, aout }; \
132
+ ret = na_ndloop3(&ndf, &opt, 3, a, x, y); \
133
+ } \
134
+ \
135
+ RB_GC_GUARD(a); \
136
+ RB_GC_GUARD(x); \
137
+ RB_GC_GUARD(y); \
138
+ \
139
+ return ret; \
136
140
  }
137
141
 
138
142
  DEF_LINALG_OPTIONS(double)
@@ -1,55 +1,55 @@
1
1
  #include "nrm2.h"
2
2
 
3
- #define DEF_LINALG_FUNC(tDType, tRtDType, tNAryClass, tRtNAryClass, fBlasFunc) \
4
- static void _iter_##fBlasFunc(na_loop_t* const lp) { \
5
- tDType* x = (tDType*)NDL_PTR(lp, 0); \
6
- tRtDType* d = (tRtDType*)NDL_PTR(lp, 1); \
7
- const blasint n = (blasint)NDL_SHAPE(lp, 0)[0]; \
8
- tRtDType ret = cblas_##fBlasFunc(n, x, 1); \
9
- *d = ret; \
10
- } \
11
- \
12
- static VALUE _linalg_blas_##fBlasFunc(int argc, VALUE* argv, VALUE self) { \
13
- VALUE x = Qnil; \
14
- VALUE kw_args = Qnil; \
15
- rb_scan_args(argc, argv, "1:", &x, &kw_args); \
16
- \
17
- ID kw_table[1] = { rb_intern("keepdims") }; \
18
- VALUE kw_values[1] = { Qundef }; \
19
- rb_get_kwargs(kw_args, kw_table, 0, 1, kw_values); \
20
- const bool keepdims = kw_values[0] != Qundef ? RTEST(kw_values[0]) : false; \
21
- \
22
- if (CLASS_OF(x) != tNAryClass) { \
23
- x = rb_funcall(tNAryClass, rb_intern("cast"), 1, x); \
24
- } \
25
- if (!RTEST(nary_check_contiguous(x))) { \
26
- x = nary_dup(x); \
27
- } \
28
- \
29
- narray_t* x_nary = NULL; \
30
- GetNArray(x, x_nary); \
31
- \
32
- if (NA_NDIM(x_nary) != 1) { \
33
- rb_raise(rb_eArgError, "x must be 1-dimensional"); \
34
- return Qnil; \
35
- } \
36
- if (NA_SIZE(x_nary) == 0) { \
37
- rb_raise(rb_eArgError, "x must not be empty"); \
38
- return Qnil; \
39
- } \
40
- \
41
- ndfunc_arg_in_t ain[1] = { { tNAryClass, 1 } }; \
42
- size_t shape_out[1] = { 1 }; \
43
- ndfunc_arg_out_t aout[1] = { { tRtNAryClass, 0, shape_out } }; \
44
- ndfunc_t ndf = { _iter_##fBlasFunc, NO_LOOP | NDF_EXTRACT, 1, 1, ain, aout }; \
45
- if (keepdims) { \
46
- ndf.flag |= NDF_KEEP_DIM; \
47
- } \
48
- \
49
- VALUE ret = na_ndloop(&ndf, 1, x); \
50
- \
51
- RB_GC_GUARD(x); \
52
- return ret; \
3
+ #define DEF_LINALG_FUNC(tDType, tRtDType, tNAryClass, tRtNAryClass, fBlasFunc) \
4
+ static void _iter_##fBlasFunc(na_loop_t* const lp) { \
5
+ tDType* x = (tDType*)NDL_PTR(lp, 0); \
6
+ tRtDType* d = (tRtDType*)NDL_PTR(lp, 1); \
7
+ const blasint n = (blasint)NDL_SHAPE(lp, 0)[0]; \
8
+ tRtDType ret = cblas_##fBlasFunc(n, x, 1); \
9
+ *d = ret; \
10
+ } \
11
+ \
12
+ static VALUE _linalg_blas_##fBlasFunc(int argc, VALUE* argv, VALUE self) { \
13
+ VALUE x = Qnil; \
14
+ VALUE kw_args = Qnil; \
15
+ rb_scan_args(argc, argv, "1:", &x, &kw_args); \
16
+ \
17
+ ID kw_table[1] = { rb_intern("keepdims") }; \
18
+ VALUE kw_values[1] = { Qundef }; \
19
+ rb_get_kwargs(kw_args, kw_table, 0, 1, kw_values); \
20
+ const bool keepdims = kw_values[0] != Qundef ? RTEST(kw_values[0]) : false; \
21
+ \
22
+ if (CLASS_OF(x) != tNAryClass) { \
23
+ x = rb_funcall(tNAryClass, rb_intern("cast"), 1, x); \
24
+ } \
25
+ if (!RTEST(nary_check_contiguous(x))) { \
26
+ x = nary_dup(x); \
27
+ } \
28
+ \
29
+ narray_t* x_nary = NULL; \
30
+ GetNArray(x, x_nary); \
31
+ \
32
+ if (NA_NDIM(x_nary) != 1) { \
33
+ rb_raise(rb_eArgError, "x must be 1-dimensional"); \
34
+ return Qnil; \
35
+ } \
36
+ if (NA_SIZE(x_nary) == 0) { \
37
+ rb_raise(rb_eArgError, "x must not be empty"); \
38
+ return Qnil; \
39
+ } \
40
+ \
41
+ ndfunc_arg_in_t ain[1] = { { tNAryClass, 1 } }; \
42
+ size_t shape_out[1] = { 1 }; \
43
+ ndfunc_arg_out_t aout[1] = { { tRtNAryClass, 0, shape_out } }; \
44
+ ndfunc_t ndf = { _iter_##fBlasFunc, NO_LOOP | NDF_EXTRACT, 1, 1, ain, aout }; \
45
+ if (keepdims) { \
46
+ ndf.flag |= NDF_KEEP_DIM; \
47
+ } \
48
+ \
49
+ VALUE ret = na_ndloop(&ndf, 1, x); \
50
+ \
51
+ RB_GC_GUARD(x); \
52
+ return ret; \
53
53
  }
54
54
 
55
55
  DEF_LINALG_FUNC(double, double, numo_cDFloat, numo_cDFloat, dnrm2)