alglib 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (255) hide show
  1. data/History.txt +7 -0
  2. data/Manifest.txt +253 -0
  3. data/README.txt +33 -0
  4. data/Rakefile +27 -0
  5. data/ext/Rakefile +24 -0
  6. data/ext/alglib.i +24 -0
  7. data/ext/alglib/Makefile +157 -0
  8. data/ext/alglib/airyf.cpp +372 -0
  9. data/ext/alglib/airyf.h +81 -0
  10. data/ext/alglib/alglib.cpp +8558 -0
  11. data/ext/alglib/alglib_util.cpp +19 -0
  12. data/ext/alglib/alglib_util.h +14 -0
  13. data/ext/alglib/ap.cpp +877 -0
  14. data/ext/alglib/ap.english.html +364 -0
  15. data/ext/alglib/ap.h +666 -0
  16. data/ext/alglib/ap.russian.html +442 -0
  17. data/ext/alglib/apvt.h +754 -0
  18. data/ext/alglib/bdss.cpp +1500 -0
  19. data/ext/alglib/bdss.h +251 -0
  20. data/ext/alglib/bdsvd.cpp +1339 -0
  21. data/ext/alglib/bdsvd.h +164 -0
  22. data/ext/alglib/bessel.cpp +1226 -0
  23. data/ext/alglib/bessel.h +331 -0
  24. data/ext/alglib/betaf.cpp +105 -0
  25. data/ext/alglib/betaf.h +74 -0
  26. data/ext/alglib/bidiagonal.cpp +1328 -0
  27. data/ext/alglib/bidiagonal.h +350 -0
  28. data/ext/alglib/binomialdistr.cpp +247 -0
  29. data/ext/alglib/binomialdistr.h +153 -0
  30. data/ext/alglib/blas.cpp +576 -0
  31. data/ext/alglib/blas.h +132 -0
  32. data/ext/alglib/cblas.cpp +226 -0
  33. data/ext/alglib/cblas.h +57 -0
  34. data/ext/alglib/cdet.cpp +138 -0
  35. data/ext/alglib/cdet.h +92 -0
  36. data/ext/alglib/chebyshev.cpp +216 -0
  37. data/ext/alglib/chebyshev.h +76 -0
  38. data/ext/alglib/chisquaredistr.cpp +157 -0
  39. data/ext/alglib/chisquaredistr.h +144 -0
  40. data/ext/alglib/cholesky.cpp +285 -0
  41. data/ext/alglib/cholesky.h +86 -0
  42. data/ext/alglib/cinverse.cpp +298 -0
  43. data/ext/alglib/cinverse.h +111 -0
  44. data/ext/alglib/clu.cpp +337 -0
  45. data/ext/alglib/clu.h +120 -0
  46. data/ext/alglib/correlation.cpp +280 -0
  47. data/ext/alglib/correlation.h +77 -0
  48. data/ext/alglib/correlationtests.cpp +726 -0
  49. data/ext/alglib/correlationtests.h +134 -0
  50. data/ext/alglib/crcond.cpp +826 -0
  51. data/ext/alglib/crcond.h +148 -0
  52. data/ext/alglib/creflections.cpp +310 -0
  53. data/ext/alglib/creflections.h +165 -0
  54. data/ext/alglib/csolve.cpp +312 -0
  55. data/ext/alglib/csolve.h +99 -0
  56. data/ext/alglib/ctrinverse.cpp +387 -0
  57. data/ext/alglib/ctrinverse.h +98 -0
  58. data/ext/alglib/ctrlinsolve.cpp +297 -0
  59. data/ext/alglib/ctrlinsolve.h +81 -0
  60. data/ext/alglib/dawson.cpp +234 -0
  61. data/ext/alglib/dawson.h +74 -0
  62. data/ext/alglib/descriptivestatistics.cpp +436 -0
  63. data/ext/alglib/descriptivestatistics.h +112 -0
  64. data/ext/alglib/det.cpp +140 -0
  65. data/ext/alglib/det.h +94 -0
  66. data/ext/alglib/dforest.cpp +1819 -0
  67. data/ext/alglib/dforest.h +316 -0
  68. data/ext/alglib/elliptic.cpp +497 -0
  69. data/ext/alglib/elliptic.h +217 -0
  70. data/ext/alglib/estnorm.cpp +429 -0
  71. data/ext/alglib/estnorm.h +107 -0
  72. data/ext/alglib/expintegrals.cpp +422 -0
  73. data/ext/alglib/expintegrals.h +108 -0
  74. data/ext/alglib/faq.english.html +258 -0
  75. data/ext/alglib/faq.russian.html +272 -0
  76. data/ext/alglib/fdistr.cpp +202 -0
  77. data/ext/alglib/fdistr.h +163 -0
  78. data/ext/alglib/fresnel.cpp +211 -0
  79. data/ext/alglib/fresnel.h +91 -0
  80. data/ext/alglib/gammaf.cpp +338 -0
  81. data/ext/alglib/gammaf.h +104 -0
  82. data/ext/alglib/gqgengauss.cpp +235 -0
  83. data/ext/alglib/gqgengauss.h +92 -0
  84. data/ext/alglib/gqgenhermite.cpp +268 -0
  85. data/ext/alglib/gqgenhermite.h +63 -0
  86. data/ext/alglib/gqgenjacobi.cpp +297 -0
  87. data/ext/alglib/gqgenjacobi.h +72 -0
  88. data/ext/alglib/gqgenlaguerre.cpp +265 -0
  89. data/ext/alglib/gqgenlaguerre.h +69 -0
  90. data/ext/alglib/gqgenlegendre.cpp +300 -0
  91. data/ext/alglib/gqgenlegendre.h +62 -0
  92. data/ext/alglib/gqgenlobatto.cpp +305 -0
  93. data/ext/alglib/gqgenlobatto.h +97 -0
  94. data/ext/alglib/gqgenradau.cpp +232 -0
  95. data/ext/alglib/gqgenradau.h +95 -0
  96. data/ext/alglib/hbisinv.cpp +480 -0
  97. data/ext/alglib/hbisinv.h +183 -0
  98. data/ext/alglib/hblas.cpp +228 -0
  99. data/ext/alglib/hblas.h +64 -0
  100. data/ext/alglib/hcholesky.cpp +339 -0
  101. data/ext/alglib/hcholesky.h +91 -0
  102. data/ext/alglib/hermite.cpp +114 -0
  103. data/ext/alglib/hermite.h +49 -0
  104. data/ext/alglib/hessenberg.cpp +370 -0
  105. data/ext/alglib/hessenberg.h +152 -0
  106. data/ext/alglib/hevd.cpp +247 -0
  107. data/ext/alglib/hevd.h +107 -0
  108. data/ext/alglib/hsschur.cpp +1316 -0
  109. data/ext/alglib/hsschur.h +108 -0
  110. data/ext/alglib/htridiagonal.cpp +734 -0
  111. data/ext/alglib/htridiagonal.h +180 -0
  112. data/ext/alglib/ialglib.cpp +6 -0
  113. data/ext/alglib/ialglib.h +9 -0
  114. data/ext/alglib/ibetaf.cpp +960 -0
  115. data/ext/alglib/ibetaf.h +125 -0
  116. data/ext/alglib/igammaf.cpp +430 -0
  117. data/ext/alglib/igammaf.h +157 -0
  118. data/ext/alglib/inv.cpp +274 -0
  119. data/ext/alglib/inv.h +115 -0
  120. data/ext/alglib/inverseupdate.cpp +480 -0
  121. data/ext/alglib/inverseupdate.h +185 -0
  122. data/ext/alglib/jacobianelliptic.cpp +164 -0
  123. data/ext/alglib/jacobianelliptic.h +94 -0
  124. data/ext/alglib/jarquebera.cpp +2271 -0
  125. data/ext/alglib/jarquebera.h +80 -0
  126. data/ext/alglib/kmeans.cpp +356 -0
  127. data/ext/alglib/kmeans.h +76 -0
  128. data/ext/alglib/laguerre.cpp +94 -0
  129. data/ext/alglib/laguerre.h +48 -0
  130. data/ext/alglib/lbfgs.cpp +1167 -0
  131. data/ext/alglib/lbfgs.h +218 -0
  132. data/ext/alglib/lda.cpp +434 -0
  133. data/ext/alglib/lda.h +133 -0
  134. data/ext/alglib/ldlt.cpp +1130 -0
  135. data/ext/alglib/ldlt.h +124 -0
  136. data/ext/alglib/leastsquares.cpp +1252 -0
  137. data/ext/alglib/leastsquares.h +290 -0
  138. data/ext/alglib/legendre.cpp +107 -0
  139. data/ext/alglib/legendre.h +49 -0
  140. data/ext/alglib/linreg.cpp +1185 -0
  141. data/ext/alglib/linreg.h +380 -0
  142. data/ext/alglib/logit.cpp +1523 -0
  143. data/ext/alglib/logit.h +333 -0
  144. data/ext/alglib/lq.cpp +399 -0
  145. data/ext/alglib/lq.h +160 -0
  146. data/ext/alglib/lu.cpp +462 -0
  147. data/ext/alglib/lu.h +119 -0
  148. data/ext/alglib/mannwhitneyu.cpp +4490 -0
  149. data/ext/alglib/mannwhitneyu.h +115 -0
  150. data/ext/alglib/minlm.cpp +918 -0
  151. data/ext/alglib/minlm.h +312 -0
  152. data/ext/alglib/mlpbase.cpp +3375 -0
  153. data/ext/alglib/mlpbase.h +589 -0
  154. data/ext/alglib/mlpe.cpp +1369 -0
  155. data/ext/alglib/mlpe.h +552 -0
  156. data/ext/alglib/mlptrain.cpp +1056 -0
  157. data/ext/alglib/mlptrain.h +283 -0
  158. data/ext/alglib/nearunityunit.cpp +91 -0
  159. data/ext/alglib/nearunityunit.h +17 -0
  160. data/ext/alglib/normaldistr.cpp +377 -0
  161. data/ext/alglib/normaldistr.h +175 -0
  162. data/ext/alglib/nsevd.cpp +1869 -0
  163. data/ext/alglib/nsevd.h +140 -0
  164. data/ext/alglib/pca.cpp +168 -0
  165. data/ext/alglib/pca.h +87 -0
  166. data/ext/alglib/poissondistr.cpp +143 -0
  167. data/ext/alglib/poissondistr.h +130 -0
  168. data/ext/alglib/polinterpolation.cpp +685 -0
  169. data/ext/alglib/polinterpolation.h +206 -0
  170. data/ext/alglib/psif.cpp +173 -0
  171. data/ext/alglib/psif.h +88 -0
  172. data/ext/alglib/qr.cpp +414 -0
  173. data/ext/alglib/qr.h +168 -0
  174. data/ext/alglib/ratinterpolation.cpp +134 -0
  175. data/ext/alglib/ratinterpolation.h +72 -0
  176. data/ext/alglib/rcond.cpp +705 -0
  177. data/ext/alglib/rcond.h +140 -0
  178. data/ext/alglib/reflections.cpp +504 -0
  179. data/ext/alglib/reflections.h +165 -0
  180. data/ext/alglib/rotations.cpp +473 -0
  181. data/ext/alglib/rotations.h +128 -0
  182. data/ext/alglib/rsolve.cpp +221 -0
  183. data/ext/alglib/rsolve.h +99 -0
  184. data/ext/alglib/sbisinv.cpp +217 -0
  185. data/ext/alglib/sbisinv.h +171 -0
  186. data/ext/alglib/sblas.cpp +185 -0
  187. data/ext/alglib/sblas.h +64 -0
  188. data/ext/alglib/schur.cpp +156 -0
  189. data/ext/alglib/schur.h +102 -0
  190. data/ext/alglib/sdet.cpp +193 -0
  191. data/ext/alglib/sdet.h +101 -0
  192. data/ext/alglib/sevd.cpp +116 -0
  193. data/ext/alglib/sevd.h +99 -0
  194. data/ext/alglib/sinverse.cpp +672 -0
  195. data/ext/alglib/sinverse.h +138 -0
  196. data/ext/alglib/spddet.cpp +138 -0
  197. data/ext/alglib/spddet.h +96 -0
  198. data/ext/alglib/spdgevd.cpp +842 -0
  199. data/ext/alglib/spdgevd.h +200 -0
  200. data/ext/alglib/spdinverse.cpp +509 -0
  201. data/ext/alglib/spdinverse.h +122 -0
  202. data/ext/alglib/spdrcond.cpp +421 -0
  203. data/ext/alglib/spdrcond.h +118 -0
  204. data/ext/alglib/spdsolve.cpp +275 -0
  205. data/ext/alglib/spdsolve.h +105 -0
  206. data/ext/alglib/spline2d.cpp +1192 -0
  207. data/ext/alglib/spline2d.h +301 -0
  208. data/ext/alglib/spline3.cpp +1264 -0
  209. data/ext/alglib/spline3.h +290 -0
  210. data/ext/alglib/srcond.cpp +595 -0
  211. data/ext/alglib/srcond.h +127 -0
  212. data/ext/alglib/ssolve.cpp +895 -0
  213. data/ext/alglib/ssolve.h +139 -0
  214. data/ext/alglib/stdafx.h +0 -0
  215. data/ext/alglib/stest.cpp +131 -0
  216. data/ext/alglib/stest.h +94 -0
  217. data/ext/alglib/studenttdistr.cpp +222 -0
  218. data/ext/alglib/studenttdistr.h +115 -0
  219. data/ext/alglib/studentttests.cpp +377 -0
  220. data/ext/alglib/studentttests.h +178 -0
  221. data/ext/alglib/svd.cpp +620 -0
  222. data/ext/alglib/svd.h +126 -0
  223. data/ext/alglib/tdbisinv.cpp +2608 -0
  224. data/ext/alglib/tdbisinv.h +228 -0
  225. data/ext/alglib/tdevd.cpp +1229 -0
  226. data/ext/alglib/tdevd.h +115 -0
  227. data/ext/alglib/tridiagonal.cpp +594 -0
  228. data/ext/alglib/tridiagonal.h +171 -0
  229. data/ext/alglib/trigintegrals.cpp +490 -0
  230. data/ext/alglib/trigintegrals.h +131 -0
  231. data/ext/alglib/trinverse.cpp +345 -0
  232. data/ext/alglib/trinverse.h +98 -0
  233. data/ext/alglib/trlinsolve.cpp +926 -0
  234. data/ext/alglib/trlinsolve.h +73 -0
  235. data/ext/alglib/tsort.cpp +405 -0
  236. data/ext/alglib/tsort.h +54 -0
  237. data/ext/alglib/variancetests.cpp +245 -0
  238. data/ext/alglib/variancetests.h +134 -0
  239. data/ext/alglib/wsr.cpp +6285 -0
  240. data/ext/alglib/wsr.h +96 -0
  241. data/ext/ap.i +97 -0
  242. data/ext/correlation.i +24 -0
  243. data/ext/extconf.rb +6 -0
  244. data/ext/logit.i +89 -0
  245. data/lib/alglib.rb +71 -0
  246. data/lib/alglib/correlation.rb +26 -0
  247. data/lib/alglib/linearregression.rb +63 -0
  248. data/lib/alglib/logit.rb +42 -0
  249. data/test/test_alglib.rb +52 -0
  250. data/test/test_correlation.rb +44 -0
  251. data/test/test_correlationtest.rb +45 -0
  252. data/test/test_linreg.rb +35 -0
  253. data/test/test_logit.rb +43 -0
  254. data/test/test_pca.rb +27 -0
  255. metadata +326 -0
@@ -0,0 +1,175 @@
1
+ /*************************************************************************
2
+ Cephes Math Library Release 2.8: June, 2000
3
+ Copyright 1984, 1987, 1988, 1992, 2000 by Stephen L. Moshier
4
+
5
+ Contributors:
6
+ * Sergey Bochkanov (ALGLIB project). Translation from C to
7
+ pseudocode.
8
+
9
+ See subroutines comments for additional copyrights.
10
+
11
+ Redistribution and use in source and binary forms, with or without
12
+ modification, are permitted provided that the following conditions are
13
+ met:
14
+
15
+ - Redistributions of source code must retain the above copyright
16
+ notice, this list of conditions and the following disclaimer.
17
+
18
+ - Redistributions in binary form must reproduce the above copyright
19
+ notice, this list of conditions and the following disclaimer listed
20
+ in this license in the documentation and/or other materials
21
+ provided with the distribution.
22
+
23
+ - Neither the name of the copyright holders nor the names of its
24
+ contributors may be used to endorse or promote products derived from
25
+ this software without specific prior written permission.
26
+
27
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
32
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
33
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38
+ *************************************************************************/
39
+
40
+ #ifndef _normaldistr_h
41
+ #define _normaldistr_h
42
+
43
+ #include "ap.h"
44
+ #include "ialglib.h"
45
+
46
+ /*************************************************************************
47
+ Error function
48
+
49
+ The integral is
50
+
51
+ x
52
+ -
53
+ 2 | | 2
54
+ erf(x) = -------- | exp( - t ) dt.
55
+ sqrt(pi) | |
56
+ -
57
+ 0
58
+
59
+ For 0 <= |x| < 1, erf(x) = x * P4(x**2)/Q5(x**2); otherwise
60
+ erf(x) = 1 - erfc(x).
61
+
62
+
63
+ ACCURACY:
64
+
65
+ Relative error:
66
+ arithmetic domain # trials peak rms
67
+ IEEE 0,1 30000 3.7e-16 1.0e-16
68
+
69
+ Cephes Math Library Release 2.8: June, 2000
70
+ Copyright 1984, 1987, 1988, 1992, 2000 by Stephen L. Moshier
71
+ *************************************************************************/
72
+ double erf(double x);
73
+
74
+
75
+ /*************************************************************************
76
+ Complementary error function
77
+
78
+ 1 - erf(x) =
79
+
80
+ inf.
81
+ -
82
+ 2 | | 2
83
+ erfc(x) = -------- | exp( - t ) dt
84
+ sqrt(pi) | |
85
+ -
86
+ x
87
+
88
+
89
+ For small x, erfc(x) = 1 - erf(x); otherwise rational
90
+ approximations are computed.
91
+
92
+
93
+ ACCURACY:
94
+
95
+ Relative error:
96
+ arithmetic domain # trials peak rms
97
+ IEEE 0,26.6417 30000 5.7e-14 1.5e-14
98
+
99
+ Cephes Math Library Release 2.8: June, 2000
100
+ Copyright 1984, 1987, 1988, 1992, 2000 by Stephen L. Moshier
101
+ *************************************************************************/
102
+ double erfc(double x);
103
+
104
+
105
+ /*************************************************************************
106
+ Normal distribution function
107
+
108
+ Returns the area under the Gaussian probability density
109
+ function, integrated from minus infinity to x:
110
+
111
+ x
112
+ -
113
+ 1 | | 2
114
+ ndtr(x) = --------- | exp( - t /2 ) dt
115
+ sqrt(2pi) | |
116
+ -
117
+ -inf.
118
+
119
+ = ( 1 + erf(z) ) / 2
120
+ = erfc(z) / 2
121
+
122
+ where z = x/sqrt(2). Computation is via the functions
123
+ erf and erfc.
124
+
125
+
126
+ ACCURACY:
127
+
128
+ Relative error:
129
+ arithmetic domain # trials peak rms
130
+ IEEE -13,0 30000 3.4e-14 6.7e-15
131
+
132
+ Cephes Math Library Release 2.8: June, 2000
133
+ Copyright 1984, 1987, 1988, 1992, 2000 by Stephen L. Moshier
134
+ *************************************************************************/
135
+ double normaldistribution(double x);
136
+
137
+
138
+ /*************************************************************************
139
+ Inverse of the error function
140
+
141
+ Cephes Math Library Release 2.8: June, 2000
142
+ Copyright 1984, 1987, 1988, 1992, 2000 by Stephen L. Moshier
143
+ *************************************************************************/
144
+ double inverf(double e);
145
+
146
+
147
+ /*************************************************************************
148
+ Inverse of Normal distribution function
149
+
150
+ Returns the argument, x, for which the area under the
151
+ Gaussian probability density function (integrated from
152
+ minus infinity to x) is equal to y.
153
+
154
+
155
+ For small arguments 0 < y < exp(-2), the program computes
156
+ z = sqrt( -2.0 * log(y) ); then the approximation is
157
+ x = z - log(z)/z - (1/z) P(1/z) / Q(1/z).
158
+ There are two rational functions P/Q, one for 0 < y < exp(-32)
159
+ and the other for y up to exp(-2). For larger arguments,
160
+ w = y - 0.5, and x/sqrt(2pi) = w + w**3 R(w**2)/S(w**2)).
161
+
162
+ ACCURACY:
163
+
164
+ Relative error:
165
+ arithmetic domain # trials peak rms
166
+ IEEE 0.125, 1 20000 7.2e-16 1.3e-16
167
+ IEEE 3e-308, 0.135 50000 4.6e-16 9.8e-17
168
+
169
+ Cephes Math Library Release 2.8: June, 2000
170
+ Copyright 1984, 1987, 1988, 1992, 2000 by Stephen L. Moshier
171
+ *************************************************************************/
172
+ double invnormaldistribution(double y0);
173
+
174
+
175
+ #endif
@@ -0,0 +1,1869 @@
1
+ /*************************************************************************
2
+ Copyright (c) 1992-2007 The University of Tennessee. All rights reserved.
3
+
4
+ Contributors:
5
+ * Sergey Bochkanov (ALGLIB project). Translation from FORTRAN to
6
+ pseudocode.
7
+
8
+ See subroutines comments for additional copyrights.
9
+
10
+ Redistribution and use in source and binary forms, with or without
11
+ modification, are permitted provided that the following conditions are
12
+ met:
13
+
14
+ - Redistributions of source code must retain the above copyright
15
+ notice, this list of conditions and the following disclaimer.
16
+
17
+ - Redistributions in binary form must reproduce the above copyright
18
+ notice, this list of conditions and the following disclaimer listed
19
+ in this license in the documentation and/or other materials
20
+ provided with the distribution.
21
+
22
+ - Neither the name of the copyright holders nor the names of its
23
+ contributors may be used to endorse or promote products derived from
24
+ this software without specific prior written permission.
25
+
26
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37
+ *************************************************************************/
38
+
39
+ #include <stdafx.h>
40
+ #include "nsevd.h"
41
+
42
+ static void internaltrevc(const ap::real_2d_array& t,
43
+ int n,
44
+ int side,
45
+ int howmny,
46
+ ap::boolean_1d_array vselect,
47
+ ap::real_2d_array& vl,
48
+ ap::real_2d_array& vr,
49
+ int& m,
50
+ int& info);
51
+ static void internalhsevdlaln2(const bool& ltrans,
52
+ const int& na,
53
+ const int& nw,
54
+ const double& smin,
55
+ const double& ca,
56
+ const ap::real_2d_array& a,
57
+ const double& d1,
58
+ const double& d2,
59
+ const ap::real_2d_array& b,
60
+ const double& wr,
61
+ const double& wi,
62
+ ap::boolean_1d_array& rswap4,
63
+ ap::boolean_1d_array& zswap4,
64
+ ap::integer_2d_array& ipivot44,
65
+ ap::real_1d_array& civ4,
66
+ ap::real_1d_array& crv4,
67
+ ap::real_2d_array& x,
68
+ double& scl,
69
+ double& xnorm,
70
+ int& info);
71
+ static void internalhsevdladiv(const double& a,
72
+ const double& b,
73
+ const double& c,
74
+ const double& d,
75
+ double& p,
76
+ double& q);
77
+
78
+ /*************************************************************************
79
+ Finding eigenvalues and eigenvectors of a general matrix
80
+
81
+ The algorithm finds eigenvalues and eigenvectors of a general matrix by
82
+ using the QR algorithm with multiple shifts. The algorithm can find
83
+ eigenvalues and both left and right eigenvectors.
84
+
85
+ The right eigenvector is a vector x such that A*x = w*x, and the left
86
+ eigenvector is a vector y such that y'*A = w*y' (here y' implies a complex
87
+ conjugate transposition of vector y).
88
+
89
+ Input parameters:
90
+ A - matrix. Array whose indexes range within [0..N-1, 0..N-1].
91
+ N - size of matrix A.
92
+ VNeeded - flag controlling whether eigenvectors are needed or not.
93
+ If VNeeded is equal to:
94
+ * 0, eigenvectors are not returned;
95
+ * 1, right eigenvectors are returned;
96
+ * 2, left eigenvectors are returned;
97
+ * 3, both left and right eigenvectors are returned.
98
+
99
+ Output parameters:
100
+ WR - real parts of eigenvalues.
101
+ Array whose index ranges within [0..N-1].
102
+ WR - imaginary parts of eigenvalues.
103
+ Array whose index ranges within [0..N-1].
104
+ VL, VR - arrays of left and right eigenvectors (if they are needed).
105
+ If WI[i]=0, the respective eigenvalue is a real number,
106
+ and it corresponds to the column number I of matrices VL/VR.
107
+ If WI[i]>0, we have a pair of complex conjugate numbers with
108
+ positive and negative imaginary parts:
109
+ the first eigenvalue WR[i] + sqrt(-1)*WI[i];
110
+ the second eigenvalue WR[i+1] + sqrt(-1)*WI[i+1];
111
+ WI[i]>0
112
+ WI[i+1] = -WI[i] < 0
113
+ In that case, the eigenvector corresponding to the first
114
+ eigenvalue is located in i and i+1 columns of matrices
115
+ VL/VR (the column number i contains the real part, and the
116
+ column number i+1 contains the imaginary part), and the vector
117
+ corresponding to the second eigenvalue is a complex conjugate to
118
+ the first vector.
119
+ Arrays whose indexes range within [0..N-1, 0..N-1].
120
+
121
+ Result:
122
+ True, if the algorithm has converged.
123
+ False, if the algorithm has not converged.
124
+
125
+ Note 1:
126
+ Some users may ask the following question: what if WI[N-1]>0?
127
+ WI[N] must contain an eigenvalue which is complex conjugate to the
128
+ N-th eigenvalue, but the array has only size N?
129
+ The answer is as follows: such a situation cannot occur because the
130
+ algorithm finds a pairs of eigenvalues, therefore, if WI[i]>0, I is
131
+ strictly less than N-1.
132
+
133
+ Note 2:
134
+ The algorithm performance depends on the value of the internal parameter
135
+ NS of the InternalSchurDecomposition subroutine which defines the number
136
+ of shifts in the QR algorithm (similarly to the block width in block-matrix
137
+ algorithms of linear algebra). If you require maximum performance
138
+ on your machine, it is recommended to adjust this parameter manually.
139
+
140
+
141
+ See also the InternalTREVC subroutine.
142
+
143
+ The algorithm is based on the LAPACK 3.0 library.
144
+ *************************************************************************/
145
+ bool rmatrixevd(ap::real_2d_array a,
146
+ int n,
147
+ int vneeded,
148
+ ap::real_1d_array& wr,
149
+ ap::real_1d_array& wi,
150
+ ap::real_2d_array& vl,
151
+ ap::real_2d_array& vr)
152
+ {
153
+ bool result;
154
+ ap::real_2d_array a1;
155
+ ap::real_2d_array vl1;
156
+ ap::real_2d_array vr1;
157
+ ap::real_1d_array wr1;
158
+ ap::real_1d_array wi1;
159
+ int i;
160
+ double mx;
161
+
162
+ ap::ap_error::make_assertion(vneeded>=0&&vneeded<=3, "RMatrixEVD: incorrect VNeeded!");
163
+ a1.setbounds(1, n, 1, n);
164
+ for(i = 1; i <= n; i++)
165
+ {
166
+ ap::vmove(&a1(i, 1), &a(i-1, 0), ap::vlen(1,n));
167
+ }
168
+ result = nonsymmetricevd(a1, n, vneeded, wr1, wi1, vl1, vr1);
169
+ if( result )
170
+ {
171
+ wr.setbounds(0, n-1);
172
+ wi.setbounds(0, n-1);
173
+ ap::vmove(&wr(0), &wr1(1), ap::vlen(0,n-1));
174
+ ap::vmove(&wi(0), &wi1(1), ap::vlen(0,n-1));
175
+ if( vneeded==2||vneeded==3 )
176
+ {
177
+ vl.setbounds(0, n-1, 0, n-1);
178
+ for(i = 0; i <= n-1; i++)
179
+ {
180
+ ap::vmove(&vl(i, 0), &vl1(i+1, 1), ap::vlen(0,n-1));
181
+ }
182
+ }
183
+ if( vneeded==1||vneeded==3 )
184
+ {
185
+ vr.setbounds(0, n-1, 0, n-1);
186
+ for(i = 0; i <= n-1; i++)
187
+ {
188
+ ap::vmove(&vr(i, 0), &vr1(i+1, 1), ap::vlen(0,n-1));
189
+ }
190
+ }
191
+ }
192
+ return result;
193
+ }
194
+
195
+
196
+ /*************************************************************************
197
+ Obsolete 1-based subroutine
198
+ *************************************************************************/
199
+ bool nonsymmetricevd(ap::real_2d_array a,
200
+ int n,
201
+ int vneeded,
202
+ ap::real_1d_array& wr,
203
+ ap::real_1d_array& wi,
204
+ ap::real_2d_array& vl,
205
+ ap::real_2d_array& vr)
206
+ {
207
+ bool result;
208
+ ap::real_2d_array s;
209
+ ap::real_1d_array tau;
210
+ ap::boolean_1d_array sel;
211
+ int i;
212
+ int info;
213
+ int m;
214
+
215
+ ap::ap_error::make_assertion(vneeded>=0&&vneeded<=3, "NonSymmetricEVD: incorrect VNeeded!");
216
+ if( vneeded==0 )
217
+ {
218
+
219
+ //
220
+ // Eigen values only
221
+ //
222
+ toupperhessenberg(a, n, tau);
223
+ internalschurdecomposition(a, n, 0, 0, wr, wi, s, info);
224
+ result = info==0;
225
+ return result;
226
+ }
227
+
228
+ //
229
+ // Eigen values and vectors
230
+ //
231
+ toupperhessenberg(a, n, tau);
232
+ unpackqfromupperhessenberg(a, n, tau, s);
233
+ internalschurdecomposition(a, n, 1, 1, wr, wi, s, info);
234
+ result = info==0;
235
+ if( !result )
236
+ {
237
+ return result;
238
+ }
239
+ if( vneeded==1||vneeded==3 )
240
+ {
241
+ vr.setbounds(1, n, 1, n);
242
+ for(i = 1; i <= n; i++)
243
+ {
244
+ ap::vmove(&vr(i, 1), &s(i, 1), ap::vlen(1,n));
245
+ }
246
+ }
247
+ if( vneeded==2||vneeded==3 )
248
+ {
249
+ vl.setbounds(1, n, 1, n);
250
+ for(i = 1; i <= n; i++)
251
+ {
252
+ ap::vmove(&vl(i, 1), &s(i, 1), ap::vlen(1,n));
253
+ }
254
+ }
255
+ internaltrevc(a, n, vneeded, 1, sel, vl, vr, m, info);
256
+ result = info==0;
257
+ return result;
258
+ }
259
+
260
+
261
+ static void internaltrevc(const ap::real_2d_array& t,
262
+ int n,
263
+ int side,
264
+ int howmny,
265
+ ap::boolean_1d_array vselect,
266
+ ap::real_2d_array& vl,
267
+ ap::real_2d_array& vr,
268
+ int& m,
269
+ int& info)
270
+ {
271
+ bool allv;
272
+ bool bothv;
273
+ bool leftv;
274
+ bool over;
275
+ bool pair;
276
+ bool rightv;
277
+ bool somev;
278
+ int i;
279
+ int ierr;
280
+ int ii;
281
+ int ip;
282
+ int iis;
283
+ int j;
284
+ int j1;
285
+ int j2;
286
+ int jnxt;
287
+ int k;
288
+ int ki;
289
+ int n2;
290
+ double beta;
291
+ double bignum;
292
+ double emax;
293
+ double ovfl;
294
+ double rec;
295
+ double remax;
296
+ double scl;
297
+ double smin;
298
+ double smlnum;
299
+ double ulp;
300
+ double unfl;
301
+ double vcrit;
302
+ double vmax;
303
+ double wi;
304
+ double wr;
305
+ double xnorm;
306
+ ap::real_2d_array x;
307
+ ap::real_1d_array work;
308
+ ap::real_1d_array temp;
309
+ ap::real_2d_array temp11;
310
+ ap::real_2d_array temp22;
311
+ ap::real_2d_array temp11b;
312
+ ap::real_2d_array temp21b;
313
+ ap::real_2d_array temp12b;
314
+ ap::real_2d_array temp22b;
315
+ bool skipflag;
316
+ int k1;
317
+ int k2;
318
+ int k3;
319
+ int k4;
320
+ double vt;
321
+ ap::boolean_1d_array rswap4;
322
+ ap::boolean_1d_array zswap4;
323
+ ap::integer_2d_array ipivot44;
324
+ ap::real_1d_array civ4;
325
+ ap::real_1d_array crv4;
326
+
327
+ x.setbounds(1, 2, 1, 2);
328
+ temp11.setbounds(1, 1, 1, 1);
329
+ temp11b.setbounds(1, 1, 1, 1);
330
+ temp21b.setbounds(1, 2, 1, 1);
331
+ temp12b.setbounds(1, 1, 1, 2);
332
+ temp22b.setbounds(1, 2, 1, 2);
333
+ temp22.setbounds(1, 2, 1, 2);
334
+ work.setbounds(1, 3*n);
335
+ temp.setbounds(1, n);
336
+ rswap4.setbounds(1, 4);
337
+ zswap4.setbounds(1, 4);
338
+ ipivot44.setbounds(1, 4, 1, 4);
339
+ civ4.setbounds(1, 4);
340
+ crv4.setbounds(1, 4);
341
+ if( howmny!=1 )
342
+ {
343
+ if( side==1||side==3 )
344
+ {
345
+ vr.setbounds(1, n, 1, n);
346
+ }
347
+ if( side==2||side==3 )
348
+ {
349
+ vl.setbounds(1, n, 1, n);
350
+ }
351
+ }
352
+
353
+ //
354
+ // Decode and test the input parameters
355
+ //
356
+ bothv = side==3;
357
+ rightv = side==1||bothv;
358
+ leftv = side==2||bothv;
359
+ allv = howmny==2;
360
+ over = howmny==1;
361
+ somev = howmny==3;
362
+ info = 0;
363
+ if( n<0 )
364
+ {
365
+ info = -2;
366
+ return;
367
+ }
368
+ if( !rightv&&!leftv )
369
+ {
370
+ info = -3;
371
+ return;
372
+ }
373
+ if( !allv&&!over&&!somev )
374
+ {
375
+ info = -4;
376
+ return;
377
+ }
378
+
379
+ //
380
+ // Set M to the number of columns required to store the selected
381
+ // eigenvectors, standardize the array SELECT if necessary, and
382
+ // test MM.
383
+ //
384
+ if( somev )
385
+ {
386
+ m = 0;
387
+ pair = false;
388
+ for(j = 1; j <= n; j++)
389
+ {
390
+ if( pair )
391
+ {
392
+ pair = false;
393
+ vselect(j) = false;
394
+ }
395
+ else
396
+ {
397
+ if( j<n )
398
+ {
399
+ if( t(j+1,j)==0 )
400
+ {
401
+ if( vselect(j) )
402
+ {
403
+ m = m+1;
404
+ }
405
+ }
406
+ else
407
+ {
408
+ pair = true;
409
+ if( vselect(j)||vselect(j+1) )
410
+ {
411
+ vselect(j) = true;
412
+ m = m+2;
413
+ }
414
+ }
415
+ }
416
+ else
417
+ {
418
+ if( vselect(n) )
419
+ {
420
+ m = m+1;
421
+ }
422
+ }
423
+ }
424
+ }
425
+ }
426
+ else
427
+ {
428
+ m = n;
429
+ }
430
+
431
+ //
432
+ // Quick return if possible.
433
+ //
434
+ if( n==0 )
435
+ {
436
+ return;
437
+ }
438
+
439
+ //
440
+ // Set the constants to control overflow.
441
+ //
442
+ unfl = ap::minrealnumber;
443
+ ovfl = 1/unfl;
444
+ ulp = ap::machineepsilon;
445
+ smlnum = unfl*(n/ulp);
446
+ bignum = (1-ulp)/smlnum;
447
+
448
+ //
449
+ // Compute 1-norm of each column of strictly upper triangular
450
+ // part of T to control overflow in triangular solver.
451
+ //
452
+ work(1) = 0;
453
+ for(j = 2; j <= n; j++)
454
+ {
455
+ work(j) = 0;
456
+ for(i = 1; i <= j-1; i++)
457
+ {
458
+ work(j) = work(j)+fabs(t(i,j));
459
+ }
460
+ }
461
+
462
+ //
463
+ // Index IP is used to specify the real or complex eigenvalue:
464
+ // IP = 0, real eigenvalue,
465
+ // 1, first of conjugate complex pair: (wr,wi)
466
+ // -1, second of conjugate complex pair: (wr,wi)
467
+ //
468
+ n2 = 2*n;
469
+ if( rightv )
470
+ {
471
+
472
+ //
473
+ // Compute right eigenvectors.
474
+ //
475
+ ip = 0;
476
+ iis = m;
477
+ for(ki = n; ki >= 1; ki--)
478
+ {
479
+ skipflag = false;
480
+ if( ip==1 )
481
+ {
482
+ skipflag = true;
483
+ }
484
+ else
485
+ {
486
+ if( ki!=1 )
487
+ {
488
+ if( t(ki,ki-1)!=0 )
489
+ {
490
+ ip = -1;
491
+ }
492
+ }
493
+ if( somev )
494
+ {
495
+ if( ip==0 )
496
+ {
497
+ if( !vselect(ki) )
498
+ {
499
+ skipflag = true;
500
+ }
501
+ }
502
+ else
503
+ {
504
+ if( !vselect(ki-1) )
505
+ {
506
+ skipflag = true;
507
+ }
508
+ }
509
+ }
510
+ }
511
+ if( !skipflag )
512
+ {
513
+
514
+ //
515
+ // Compute the KI-th eigenvalue (WR,WI).
516
+ //
517
+ wr = t(ki,ki);
518
+ wi = 0;
519
+ if( ip!=0 )
520
+ {
521
+ wi = sqrt(fabs(t(ki,ki-1)))*sqrt(fabs(t(ki-1,ki)));
522
+ }
523
+ smin = ap::maxreal(ulp*(fabs(wr)+fabs(wi)), smlnum);
524
+ if( ip==0 )
525
+ {
526
+
527
+ //
528
+ // Real right eigenvector
529
+ //
530
+ work(ki+n) = 1;
531
+
532
+ //
533
+ // Form right-hand side
534
+ //
535
+ for(k = 1; k <= ki-1; k++)
536
+ {
537
+ work(k+n) = -t(k,ki);
538
+ }
539
+
540
+ //
541
+ // Solve the upper quasi-triangular system:
542
+ // (T(1:KI-1,1:KI-1) - WR)*X = SCALE*WORK.
543
+ //
544
+ jnxt = ki-1;
545
+ for(j = ki-1; j >= 1; j--)
546
+ {
547
+ if( j>jnxt )
548
+ {
549
+ continue;
550
+ }
551
+ j1 = j;
552
+ j2 = j;
553
+ jnxt = j-1;
554
+ if( j>1 )
555
+ {
556
+ if( t(j,j-1)!=0 )
557
+ {
558
+ j1 = j-1;
559
+ jnxt = j-2;
560
+ }
561
+ }
562
+ if( j1==j2 )
563
+ {
564
+
565
+ //
566
+ // 1-by-1 diagonal block
567
+ //
568
+ temp11(1,1) = t(j,j);
569
+ temp11b(1,1) = work(j+n);
570
+ internalhsevdlaln2(false, 1, 1, smin, double(1), temp11, 1.0, 1.0, temp11b, wr, 0.0, rswap4, zswap4, ipivot44, civ4, crv4, x, scl, xnorm, ierr);
571
+
572
+ //
573
+ // Scale X(1,1) to avoid overflow when updating
574
+ // the right-hand side.
575
+ //
576
+ if( xnorm>1 )
577
+ {
578
+ if( work(j)>bignum/xnorm )
579
+ {
580
+ x(1,1) = x(1,1)/xnorm;
581
+ scl = scl/xnorm;
582
+ }
583
+ }
584
+
585
+ //
586
+ // Scale if necessary
587
+ //
588
+ if( scl!=1 )
589
+ {
590
+ k1 = n+1;
591
+ k2 = n+ki;
592
+ ap::vmul(&work(k1), ap::vlen(k1,k2), scl);
593
+ }
594
+ work(j+n) = x(1,1);
595
+
596
+ //
597
+ // Update right-hand side
598
+ //
599
+ k1 = 1+n;
600
+ k2 = j-1+n;
601
+ k3 = j-1;
602
+ vt = -x(1,1);
603
+ ap::vadd(work.getvector(k1, k2), t.getcolumn(j, 1, k3), vt);
604
+ }
605
+ else
606
+ {
607
+
608
+ //
609
+ // 2-by-2 diagonal block
610
+ //
611
+ temp22(1,1) = t(j-1,j-1);
612
+ temp22(1,2) = t(j-1,j);
613
+ temp22(2,1) = t(j,j-1);
614
+ temp22(2,2) = t(j,j);
615
+ temp21b(1,1) = work(j-1+n);
616
+ temp21b(2,1) = work(j+n);
617
+ internalhsevdlaln2(false, 2, 1, smin, 1.0, temp22, 1.0, 1.0, temp21b, wr, double(0), rswap4, zswap4, ipivot44, civ4, crv4, x, scl, xnorm, ierr);
618
+
619
+ //
620
+ // Scale X(1,1) and X(2,1) to avoid overflow when
621
+ // updating the right-hand side.
622
+ //
623
+ if( xnorm>1 )
624
+ {
625
+ beta = ap::maxreal(work(j-1), work(j));
626
+ if( beta>bignum/xnorm )
627
+ {
628
+ x(1,1) = x(1,1)/xnorm;
629
+ x(2,1) = x(2,1)/xnorm;
630
+ scl = scl/xnorm;
631
+ }
632
+ }
633
+
634
+ //
635
+ // Scale if necessary
636
+ //
637
+ if( scl!=1 )
638
+ {
639
+ k1 = 1+n;
640
+ k2 = ki+n;
641
+ ap::vmul(&work(k1), ap::vlen(k1,k2), scl);
642
+ }
643
+ work(j-1+n) = x(1,1);
644
+ work(j+n) = x(2,1);
645
+
646
+ //
647
+ // Update right-hand side
648
+ //
649
+ k1 = 1+n;
650
+ k2 = j-2+n;
651
+ k3 = j-2;
652
+ k4 = j-1;
653
+ vt = -x(1,1);
654
+ ap::vadd(work.getvector(k1, k2), t.getcolumn(k4, 1, k3), vt);
655
+ vt = -x(2,1);
656
+ ap::vadd(work.getvector(k1, k2), t.getcolumn(j, 1, k3), vt);
657
+ }
658
+ }
659
+
660
+ //
661
+ // Copy the vector x or Q*x to VR and normalize.
662
+ //
663
+ if( !over )
664
+ {
665
+ k1 = 1+n;
666
+ k2 = ki+n;
667
+ ap::vmove(vr.getcolumn(iis, 1, ki), work.getvector(k1, k2));
668
+ ii = columnidxabsmax(vr, 1, ki, iis);
669
+ remax = 1/fabs(vr(ii,iis));
670
+ ap::vmul(vr.getcolumn(iis, 1, ki), remax);
671
+ for(k = ki+1; k <= n; k++)
672
+ {
673
+ vr(k,iis) = 0;
674
+ }
675
+ }
676
+ else
677
+ {
678
+ if( ki>1 )
679
+ {
680
+ ap::vmove(temp.getvector(1, n), vr.getcolumn(ki, 1, n));
681
+ matrixvectormultiply(vr, 1, n, 1, ki-1, false, work, 1+n, ki-1+n, 1.0, temp, 1, n, work(ki+n));
682
+ ap::vmove(vr.getcolumn(ki, 1, n), temp.getvector(1, n));
683
+ }
684
+ ii = columnidxabsmax(vr, 1, n, ki);
685
+ remax = 1/fabs(vr(ii,ki));
686
+ ap::vmul(vr.getcolumn(ki, 1, n), remax);
687
+ }
688
+ }
689
+ else
690
+ {
691
+
692
+ //
693
+ // Complex right eigenvector.
694
+ //
695
+ // Initial solve
696
+ // [ (T(KI-1,KI-1) T(KI-1,KI) ) - (WR + I* WI)]*X = 0.
697
+ // [ (T(KI,KI-1) T(KI,KI) ) ]
698
+ //
699
+ if( fabs(t(ki-1,ki))>=fabs(t(ki,ki-1)) )
700
+ {
701
+ work(ki-1+n) = 1;
702
+ work(ki+n2) = wi/t(ki-1,ki);
703
+ }
704
+ else
705
+ {
706
+ work(ki-1+n) = -wi/t(ki,ki-1);
707
+ work(ki+n2) = 1;
708
+ }
709
+ work(ki+n) = 0;
710
+ work(ki-1+n2) = 0;
711
+
712
+ //
713
+ // Form right-hand side
714
+ //
715
+ for(k = 1; k <= ki-2; k++)
716
+ {
717
+ work(k+n) = -work(ki-1+n)*t(k,ki-1);
718
+ work(k+n2) = -work(ki+n2)*t(k,ki);
719
+ }
720
+
721
+ //
722
+ // Solve upper quasi-triangular system:
723
+ // (T(1:KI-2,1:KI-2) - (WR+i*WI))*X = SCALE*(WORK+i*WORK2)
724
+ //
725
+ jnxt = ki-2;
726
+ for(j = ki-2; j >= 1; j--)
727
+ {
728
+ if( j>jnxt )
729
+ {
730
+ continue;
731
+ }
732
+ j1 = j;
733
+ j2 = j;
734
+ jnxt = j-1;
735
+ if( j>1 )
736
+ {
737
+ if( t(j,j-1)!=0 )
738
+ {
739
+ j1 = j-1;
740
+ jnxt = j-2;
741
+ }
742
+ }
743
+ if( j1==j2 )
744
+ {
745
+
746
+ //
747
+ // 1-by-1 diagonal block
748
+ //
749
+ temp11(1,1) = t(j,j);
750
+ temp12b(1,1) = work(j+n);
751
+ temp12b(1,2) = work(j+n+n);
752
+ internalhsevdlaln2(false, 1, 2, smin, 1.0, temp11, 1.0, 1.0, temp12b, wr, wi, rswap4, zswap4, ipivot44, civ4, crv4, x, scl, xnorm, ierr);
753
+
754
+ //
755
+ // Scale X(1,1) and X(1,2) to avoid overflow when
756
+ // updating the right-hand side.
757
+ //
758
+ if( xnorm>1 )
759
+ {
760
+ if( work(j)>bignum/xnorm )
761
+ {
762
+ x(1,1) = x(1,1)/xnorm;
763
+ x(1,2) = x(1,2)/xnorm;
764
+ scl = scl/xnorm;
765
+ }
766
+ }
767
+
768
+ //
769
+ // Scale if necessary
770
+ //
771
+ if( scl!=1 )
772
+ {
773
+ k1 = 1+n;
774
+ k2 = ki+n;
775
+ ap::vmul(&work(k1), ap::vlen(k1,k2), scl);
776
+ k1 = 1+n2;
777
+ k2 = ki+n2;
778
+ ap::vmul(&work(k1), ap::vlen(k1,k2), scl);
779
+ }
780
+ work(j+n) = x(1,1);
781
+ work(j+n2) = x(1,2);
782
+
783
+ //
784
+ // Update the right-hand side
785
+ //
786
+ k1 = 1+n;
787
+ k2 = j-1+n;
788
+ k3 = 1;
789
+ k4 = j-1;
790
+ vt = -x(1,1);
791
+ ap::vadd(work.getvector(k1, k2), t.getcolumn(j, k3, k4), vt);
792
+ k1 = 1+n2;
793
+ k2 = j-1+n2;
794
+ k3 = 1;
795
+ k4 = j-1;
796
+ vt = -x(1,2);
797
+ ap::vadd(work.getvector(k1, k2), t.getcolumn(j, k3, k4), vt);
798
+ }
799
+ else
800
+ {
801
+
802
+ //
803
+ // 2-by-2 diagonal block
804
+ //
805
+ temp22(1,1) = t(j-1,j-1);
806
+ temp22(1,2) = t(j-1,j);
807
+ temp22(2,1) = t(j,j-1);
808
+ temp22(2,2) = t(j,j);
809
+ temp22b(1,1) = work(j-1+n);
810
+ temp22b(1,2) = work(j-1+n+n);
811
+ temp22b(2,1) = work(j+n);
812
+ temp22b(2,2) = work(j+n+n);
813
+ internalhsevdlaln2(false, 2, 2, smin, 1.0, temp22, 1.0, 1.0, temp22b, wr, wi, rswap4, zswap4, ipivot44, civ4, crv4, x, scl, xnorm, ierr);
814
+
815
+ //
816
+ // Scale X to avoid overflow when updating
817
+ // the right-hand side.
818
+ //
819
+ if( xnorm>1 )
820
+ {
821
+ beta = ap::maxreal(work(j-1), work(j));
822
+ if( beta>bignum/xnorm )
823
+ {
824
+ rec = 1/xnorm;
825
+ x(1,1) = x(1,1)*rec;
826
+ x(1,2) = x(1,2)*rec;
827
+ x(2,1) = x(2,1)*rec;
828
+ x(2,2) = x(2,2)*rec;
829
+ scl = scl*rec;
830
+ }
831
+ }
832
+
833
+ //
834
+ // Scale if necessary
835
+ //
836
+ if( scl!=1 )
837
+ {
838
+ ap::vmul(&work(1+n), ap::vlen(1+n,ki+n), scl);
839
+ ap::vmul(&work(1+n2), ap::vlen(1+n2,ki+n2), scl);
840
+ }
841
+ work(j-1+n) = x(1,1);
842
+ work(j+n) = x(2,1);
843
+ work(j-1+n2) = x(1,2);
844
+ work(j+n2) = x(2,2);
845
+
846
+ //
847
+ // Update the right-hand side
848
+ //
849
+ vt = -x(1,1);
850
+ ap::vadd(work.getvector(n+1, n+j-2), t.getcolumn(j-1, 1, j-2), vt);
851
+ vt = -x(2,1);
852
+ ap::vadd(work.getvector(n+1, n+j-2), t.getcolumn(j, 1, j-2), vt);
853
+ vt = -x(1,2);
854
+ ap::vadd(work.getvector(n2+1, n2+j-2), t.getcolumn(j-1, 1, j-2), vt);
855
+ vt = -x(2,2);
856
+ ap::vadd(work.getvector(n2+1, n2+j-2), t.getcolumn(j, 1, j-2), vt);
857
+ }
858
+ }
859
+
860
+ //
861
+ // Copy the vector x or Q*x to VR and normalize.
862
+ //
863
+ if( !over )
864
+ {
865
+ ap::vmove(vr.getcolumn(iis-1, 1, ki), work.getvector(n+1, n+ki));
866
+ ap::vmove(vr.getcolumn(iis, 1, ki), work.getvector(n2+1, n2+ki));
867
+ emax = 0;
868
+ for(k = 1; k <= ki; k++)
869
+ {
870
+ emax = ap::maxreal(emax, fabs(vr(k,iis-1))+fabs(vr(k,iis)));
871
+ }
872
+ remax = 1/emax;
873
+ ap::vmul(vr.getcolumn(iis-1, 1, ki), remax);
874
+ ap::vmul(vr.getcolumn(iis, 1, ki), remax);
875
+ for(k = ki+1; k <= n; k++)
876
+ {
877
+ vr(k,iis-1) = 0;
878
+ vr(k,iis) = 0;
879
+ }
880
+ }
881
+ else
882
+ {
883
+ if( ki>2 )
884
+ {
885
+ ap::vmove(temp.getvector(1, n), vr.getcolumn(ki-1, 1, n));
886
+ matrixvectormultiply(vr, 1, n, 1, ki-2, false, work, 1+n, ki-2+n, 1.0, temp, 1, n, work(ki-1+n));
887
+ ap::vmove(vr.getcolumn(ki-1, 1, n), temp.getvector(1, n));
888
+ ap::vmove(temp.getvector(1, n), vr.getcolumn(ki, 1, n));
889
+ matrixvectormultiply(vr, 1, n, 1, ki-2, false, work, 1+n2, ki-2+n2, 1.0, temp, 1, n, work(ki+n2));
890
+ ap::vmove(vr.getcolumn(ki, 1, n), temp.getvector(1, n));
891
+ }
892
+ else
893
+ {
894
+ vt = work(ki-1+n);
895
+ ap::vmul(vr.getcolumn(ki-1, 1, n), vt);
896
+ vt = work(ki+n2);
897
+ ap::vmul(vr.getcolumn(ki, 1, n), vt);
898
+ }
899
+ emax = 0;
900
+ for(k = 1; k <= n; k++)
901
+ {
902
+ emax = ap::maxreal(emax, fabs(vr(k,ki-1))+fabs(vr(k,ki)));
903
+ }
904
+ remax = 1/emax;
905
+ ap::vmul(vr.getcolumn(ki-1, 1, n), remax);
906
+ ap::vmul(vr.getcolumn(ki, 1, n), remax);
907
+ }
908
+ }
909
+ iis = iis-1;
910
+ if( ip!=0 )
911
+ {
912
+ iis = iis-1;
913
+ }
914
+ }
915
+ if( ip==1 )
916
+ {
917
+ ip = 0;
918
+ }
919
+ if( ip==-1 )
920
+ {
921
+ ip = 1;
922
+ }
923
+ }
924
+ }
925
+ if( leftv )
926
+ {
927
+
928
+ //
929
+ // Compute left eigenvectors.
930
+ //
931
+ ip = 0;
932
+ iis = 1;
933
+ for(ki = 1; ki <= n; ki++)
934
+ {
935
+ skipflag = false;
936
+ if( ip==-1 )
937
+ {
938
+ skipflag = true;
939
+ }
940
+ else
941
+ {
942
+ if( ki!=n )
943
+ {
944
+ if( t(ki+1,ki)!=0 )
945
+ {
946
+ ip = 1;
947
+ }
948
+ }
949
+ if( somev )
950
+ {
951
+ if( !vselect(ki) )
952
+ {
953
+ skipflag = true;
954
+ }
955
+ }
956
+ }
957
+ if( !skipflag )
958
+ {
959
+
960
+ //
961
+ // Compute the KI-th eigenvalue (WR,WI).
962
+ //
963
+ wr = t(ki,ki);
964
+ wi = 0;
965
+ if( ip!=0 )
966
+ {
967
+ wi = sqrt(fabs(t(ki,ki+1)))*sqrt(fabs(t(ki+1,ki)));
968
+ }
969
+ smin = ap::maxreal(ulp*(fabs(wr)+fabs(wi)), smlnum);
970
+ if( ip==0 )
971
+ {
972
+
973
+ //
974
+ // Real left eigenvector.
975
+ //
976
+ work(ki+n) = 1;
977
+
978
+ //
979
+ // Form right-hand side
980
+ //
981
+ for(k = ki+1; k <= n; k++)
982
+ {
983
+ work(k+n) = -t(ki,k);
984
+ }
985
+
986
+ //
987
+ // Solve the quasi-triangular system:
988
+ // (T(KI+1:N,KI+1:N) - WR)'*X = SCALE*WORK
989
+ //
990
+ vmax = 1;
991
+ vcrit = bignum;
992
+ jnxt = ki+1;
993
+ for(j = ki+1; j <= n; j++)
994
+ {
995
+ if( j<jnxt )
996
+ {
997
+ continue;
998
+ }
999
+ j1 = j;
1000
+ j2 = j;
1001
+ jnxt = j+1;
1002
+ if( j<n )
1003
+ {
1004
+ if( t(j+1,j)!=0 )
1005
+ {
1006
+ j2 = j+1;
1007
+ jnxt = j+2;
1008
+ }
1009
+ }
1010
+ if( j1==j2 )
1011
+ {
1012
+
1013
+ //
1014
+ // 1-by-1 diagonal block
1015
+ //
1016
+ // Scale if necessary to avoid overflow when forming
1017
+ // the right-hand side.
1018
+ //
1019
+ if( work(j)>vcrit )
1020
+ {
1021
+ rec = 1/vmax;
1022
+ ap::vmul(&work(ki+n), ap::vlen(ki+n,n+n), rec);
1023
+ vmax = 1;
1024
+ vcrit = bignum;
1025
+ }
1026
+ vt = ap::vdotproduct(t.getcolumn(j, ki+1, j-1), work.getvector(ki+1+n, j-1+n));
1027
+ work(j+n) = work(j+n)-vt;
1028
+
1029
+ //
1030
+ // Solve (T(J,J)-WR)'*X = WORK
1031
+ //
1032
+ temp11(1,1) = t(j,j);
1033
+ temp11b(1,1) = work(j+n);
1034
+ internalhsevdlaln2(false, 1, 1, smin, 1.0, temp11, 1.0, 1.0, temp11b, wr, double(0), rswap4, zswap4, ipivot44, civ4, crv4, x, scl, xnorm, ierr);
1035
+
1036
+ //
1037
+ // Scale if necessary
1038
+ //
1039
+ if( scl!=1 )
1040
+ {
1041
+ ap::vmul(&work(ki+n), ap::vlen(ki+n,n+n), scl);
1042
+ }
1043
+ work(j+n) = x(1,1);
1044
+ vmax = ap::maxreal(fabs(work(j+n)), vmax);
1045
+ vcrit = bignum/vmax;
1046
+ }
1047
+ else
1048
+ {
1049
+
1050
+ //
1051
+ // 2-by-2 diagonal block
1052
+ //
1053
+ // Scale if necessary to avoid overflow when forming
1054
+ // the right-hand side.
1055
+ //
1056
+ beta = ap::maxreal(work(j), work(j+1));
1057
+ if( beta>vcrit )
1058
+ {
1059
+ rec = 1/vmax;
1060
+ ap::vmul(&work(ki+n), ap::vlen(ki+n,n+n), rec);
1061
+ vmax = 1;
1062
+ vcrit = bignum;
1063
+ }
1064
+ vt = ap::vdotproduct(t.getcolumn(j, ki+1, j-1), work.getvector(ki+1+n, j-1+n));
1065
+ work(j+n) = work(j+n)-vt;
1066
+ vt = ap::vdotproduct(t.getcolumn(j+1, ki+1, j-1), work.getvector(ki+1+n, j-1+n));
1067
+ work(j+1+n) = work(j+1+n)-vt;
1068
+
1069
+ //
1070
+ // Solve
1071
+ // [T(J,J)-WR T(J,J+1) ]'* X = SCALE*( WORK1 )
1072
+ // [T(J+1,J) T(J+1,J+1)-WR] ( WORK2 )
1073
+ //
1074
+ temp22(1,1) = t(j,j);
1075
+ temp22(1,2) = t(j,j+1);
1076
+ temp22(2,1) = t(j+1,j);
1077
+ temp22(2,2) = t(j+1,j+1);
1078
+ temp21b(1,1) = work(j+n);
1079
+ temp21b(2,1) = work(j+1+n);
1080
+ internalhsevdlaln2(true, 2, 1, smin, 1.0, temp22, 1.0, 1.0, temp21b, wr, double(0), rswap4, zswap4, ipivot44, civ4, crv4, x, scl, xnorm, ierr);
1081
+
1082
+ //
1083
+ // Scale if necessary
1084
+ //
1085
+ if( scl!=1 )
1086
+ {
1087
+ ap::vmul(&work(ki+n), ap::vlen(ki+n,n+n), scl);
1088
+ }
1089
+ work(j+n) = x(1,1);
1090
+ work(j+1+n) = x(2,1);
1091
+ vmax = ap::maxreal(fabs(work(j+n)), ap::maxreal(fabs(work(j+1+n)), vmax));
1092
+ vcrit = bignum/vmax;
1093
+ }
1094
+ }
1095
+
1096
+ //
1097
+ // Copy the vector x or Q*x to VL and normalize.
1098
+ //
1099
+ if( !over )
1100
+ {
1101
+ ap::vmove(vl.getcolumn(iis, ki, n), work.getvector(ki+n, n+n));
1102
+ ii = columnidxabsmax(vl, ki, n, iis);
1103
+ remax = 1/fabs(vl(ii,iis));
1104
+ ap::vmul(vl.getcolumn(iis, ki, n), remax);
1105
+ for(k = 1; k <= ki-1; k++)
1106
+ {
1107
+ vl(k,iis) = 0;
1108
+ }
1109
+ }
1110
+ else
1111
+ {
1112
+ if( ki<n )
1113
+ {
1114
+ ap::vmove(temp.getvector(1, n), vl.getcolumn(ki, 1, n));
1115
+ matrixvectormultiply(vl, 1, n, ki+1, n, false, work, ki+1+n, n+n, 1.0, temp, 1, n, work(ki+n));
1116
+ ap::vmove(vl.getcolumn(ki, 1, n), temp.getvector(1, n));
1117
+ }
1118
+ ii = columnidxabsmax(vl, 1, n, ki);
1119
+ remax = 1/fabs(vl(ii,ki));
1120
+ ap::vmul(vl.getcolumn(ki, 1, n), remax);
1121
+ }
1122
+ }
1123
+ else
1124
+ {
1125
+
1126
+ //
1127
+ // Complex left eigenvector.
1128
+ //
1129
+ // Initial solve:
1130
+ // ((T(KI,KI) T(KI,KI+1) )' - (WR - I* WI))*X = 0.
1131
+ // ((T(KI+1,KI) T(KI+1,KI+1)) )
1132
+ //
1133
+ if( fabs(t(ki,ki+1))>=fabs(t(ki+1,ki)) )
1134
+ {
1135
+ work(ki+n) = wi/t(ki,ki+1);
1136
+ work(ki+1+n2) = 1;
1137
+ }
1138
+ else
1139
+ {
1140
+ work(ki+n) = 1;
1141
+ work(ki+1+n2) = -wi/t(ki+1,ki);
1142
+ }
1143
+ work(ki+1+n) = 0;
1144
+ work(ki+n2) = 0;
1145
+
1146
+ //
1147
+ // Form right-hand side
1148
+ //
1149
+ for(k = ki+2; k <= n; k++)
1150
+ {
1151
+ work(k+n) = -work(ki+n)*t(ki,k);
1152
+ work(k+n2) = -work(ki+1+n2)*t(ki+1,k);
1153
+ }
1154
+
1155
+ //
1156
+ // Solve complex quasi-triangular system:
1157
+ // ( T(KI+2,N:KI+2,N) - (WR-i*WI) )*X = WORK1+i*WORK2
1158
+ //
1159
+ vmax = 1;
1160
+ vcrit = bignum;
1161
+ jnxt = ki+2;
1162
+ for(j = ki+2; j <= n; j++)
1163
+ {
1164
+ if( j<jnxt )
1165
+ {
1166
+ continue;
1167
+ }
1168
+ j1 = j;
1169
+ j2 = j;
1170
+ jnxt = j+1;
1171
+ if( j<n )
1172
+ {
1173
+ if( t(j+1,j)!=0 )
1174
+ {
1175
+ j2 = j+1;
1176
+ jnxt = j+2;
1177
+ }
1178
+ }
1179
+ if( j1==j2 )
1180
+ {
1181
+
1182
+ //
1183
+ // 1-by-1 diagonal block
1184
+ //
1185
+ // Scale if necessary to avoid overflow when
1186
+ // forming the right-hand side elements.
1187
+ //
1188
+ if( work(j)>vcrit )
1189
+ {
1190
+ rec = 1/vmax;
1191
+ ap::vmul(&work(ki+n), ap::vlen(ki+n,n+n), rec);
1192
+ ap::vmul(&work(ki+n2), ap::vlen(ki+n2,n+n2), rec);
1193
+ vmax = 1;
1194
+ vcrit = bignum;
1195
+ }
1196
+ vt = ap::vdotproduct(t.getcolumn(j, ki+2, j-1), work.getvector(ki+2+n, j-1+n));
1197
+ work(j+n) = work(j+n)-vt;
1198
+ vt = ap::vdotproduct(t.getcolumn(j, ki+2, j-1), work.getvector(ki+2+n2, j-1+n2));
1199
+ work(j+n2) = work(j+n2)-vt;
1200
+
1201
+ //
1202
+ // Solve (T(J,J)-(WR-i*WI))*(X11+i*X12)= WK+I*WK2
1203
+ //
1204
+ temp11(1,1) = t(j,j);
1205
+ temp12b(1,1) = work(j+n);
1206
+ temp12b(1,2) = work(j+n+n);
1207
+ internalhsevdlaln2(false, 1, 2, smin, 1.0, temp11, 1.0, 1.0, temp12b, wr, -wi, rswap4, zswap4, ipivot44, civ4, crv4, x, scl, xnorm, ierr);
1208
+
1209
+ //
1210
+ // Scale if necessary
1211
+ //
1212
+ if( scl!=1 )
1213
+ {
1214
+ ap::vmul(&work(ki+n), ap::vlen(ki+n,n+n), scl);
1215
+ ap::vmul(&work(ki+n2), ap::vlen(ki+n2,n+n2), scl);
1216
+ }
1217
+ work(j+n) = x(1,1);
1218
+ work(j+n2) = x(1,2);
1219
+ vmax = ap::maxreal(fabs(work(j+n)), ap::maxreal(fabs(work(j+n2)), vmax));
1220
+ vcrit = bignum/vmax;
1221
+ }
1222
+ else
1223
+ {
1224
+
1225
+ //
1226
+ // 2-by-2 diagonal block
1227
+ //
1228
+ // Scale if necessary to avoid overflow when forming
1229
+ // the right-hand side elements.
1230
+ //
1231
+ beta = ap::maxreal(work(j), work(j+1));
1232
+ if( beta>vcrit )
1233
+ {
1234
+ rec = 1/vmax;
1235
+ ap::vmul(&work(ki+n), ap::vlen(ki+n,n+n), rec);
1236
+ ap::vmul(&work(ki+n2), ap::vlen(ki+n2,n+n2), rec);
1237
+ vmax = 1;
1238
+ vcrit = bignum;
1239
+ }
1240
+ vt = ap::vdotproduct(t.getcolumn(j, ki+2, j-1), work.getvector(ki+2+n, j-1+n));
1241
+ work(j+n) = work(j+n)-vt;
1242
+ vt = ap::vdotproduct(t.getcolumn(j, ki+2, j-1), work.getvector(ki+2+n2, j-1+n2));
1243
+ work(j+n2) = work(j+n2)-vt;
1244
+ vt = ap::vdotproduct(t.getcolumn(j+1, ki+2, j-1), work.getvector(ki+2+n, j-1+n));
1245
+ work(j+1+n) = work(j+1+n)-vt;
1246
+ vt = ap::vdotproduct(t.getcolumn(j+1, ki+2, j-1), work.getvector(ki+2+n2, j-1+n2));
1247
+ work(j+1+n2) = work(j+1+n2)-vt;
1248
+
1249
+ //
1250
+ // Solve 2-by-2 complex linear equation
1251
+ // ([T(j,j) T(j,j+1) ]'-(wr-i*wi)*I)*X = SCALE*B
1252
+ // ([T(j+1,j) T(j+1,j+1)] )
1253
+ //
1254
+ temp22(1,1) = t(j,j);
1255
+ temp22(1,2) = t(j,j+1);
1256
+ temp22(2,1) = t(j+1,j);
1257
+ temp22(2,2) = t(j+1,j+1);
1258
+ temp22b(1,1) = work(j+n);
1259
+ temp22b(1,2) = work(j+n+n);
1260
+ temp22b(2,1) = work(j+1+n);
1261
+ temp22b(2,2) = work(j+1+n+n);
1262
+ internalhsevdlaln2(true, 2, 2, smin, 1.0, temp22, 1.0, 1.0, temp22b, wr, -wi, rswap4, zswap4, ipivot44, civ4, crv4, x, scl, xnorm, ierr);
1263
+
1264
+ //
1265
+ // Scale if necessary
1266
+ //
1267
+ if( scl!=1 )
1268
+ {
1269
+ ap::vmul(&work(ki+n), ap::vlen(ki+n,n+n), scl);
1270
+ ap::vmul(&work(ki+n2), ap::vlen(ki+n2,n+n2), scl);
1271
+ }
1272
+ work(j+n) = x(1,1);
1273
+ work(j+n2) = x(1,2);
1274
+ work(j+1+n) = x(2,1);
1275
+ work(j+1+n2) = x(2,2);
1276
+ vmax = ap::maxreal(fabs(x(1,1)), vmax);
1277
+ vmax = ap::maxreal(fabs(x(1,2)), vmax);
1278
+ vmax = ap::maxreal(fabs(x(2,1)), vmax);
1279
+ vmax = ap::maxreal(fabs(x(2,2)), vmax);
1280
+ vcrit = bignum/vmax;
1281
+ }
1282
+ }
1283
+
1284
+ //
1285
+ // Copy the vector x or Q*x to VL and normalize.
1286
+ //
1287
+ if( !over )
1288
+ {
1289
+ ap::vmove(vl.getcolumn(iis, ki, n), work.getvector(ki+n, n+n));
1290
+ ap::vmove(vl.getcolumn(iis+1, ki, n), work.getvector(ki+n2, n+n2));
1291
+ emax = 0;
1292
+ for(k = ki; k <= n; k++)
1293
+ {
1294
+ emax = ap::maxreal(emax, fabs(vl(k,iis))+fabs(vl(k,iis+1)));
1295
+ }
1296
+ remax = 1/emax;
1297
+ ap::vmul(vl.getcolumn(iis, ki, n), remax);
1298
+ ap::vmul(vl.getcolumn(iis+1, ki, n), remax);
1299
+ for(k = 1; k <= ki-1; k++)
1300
+ {
1301
+ vl(k,iis) = 0;
1302
+ vl(k,iis+1) = 0;
1303
+ }
1304
+ }
1305
+ else
1306
+ {
1307
+ if( ki<n-1 )
1308
+ {
1309
+ ap::vmove(temp.getvector(1, n), vl.getcolumn(ki, 1, n));
1310
+ matrixvectormultiply(vl, 1, n, ki+2, n, false, work, ki+2+n, n+n, 1.0, temp, 1, n, work(ki+n));
1311
+ ap::vmove(vl.getcolumn(ki, 1, n), temp.getvector(1, n));
1312
+ ap::vmove(temp.getvector(1, n), vl.getcolumn(ki+1, 1, n));
1313
+ matrixvectormultiply(vl, 1, n, ki+2, n, false, work, ki+2+n2, n+n2, 1.0, temp, 1, n, work(ki+1+n2));
1314
+ ap::vmove(vl.getcolumn(ki+1, 1, n), temp.getvector(1, n));
1315
+ }
1316
+ else
1317
+ {
1318
+ vt = work(ki+n);
1319
+ ap::vmul(vl.getcolumn(ki, 1, n), vt);
1320
+ vt = work(ki+1+n2);
1321
+ ap::vmul(vl.getcolumn(ki+1, 1, n), vt);
1322
+ }
1323
+ emax = 0;
1324
+ for(k = 1; k <= n; k++)
1325
+ {
1326
+ emax = ap::maxreal(emax, fabs(vl(k,ki))+fabs(vl(k,ki+1)));
1327
+ }
1328
+ remax = 1/emax;
1329
+ ap::vmul(vl.getcolumn(ki, 1, n), remax);
1330
+ ap::vmul(vl.getcolumn(ki+1, 1, n), remax);
1331
+ }
1332
+ }
1333
+ iis = iis+1;
1334
+ if( ip!=0 )
1335
+ {
1336
+ iis = iis+1;
1337
+ }
1338
+ }
1339
+ if( ip==-1 )
1340
+ {
1341
+ ip = 0;
1342
+ }
1343
+ if( ip==1 )
1344
+ {
1345
+ ip = -1;
1346
+ }
1347
+ }
1348
+ }
1349
+ }
1350
+
1351
+
1352
+ static void internalhsevdlaln2(const bool& ltrans,
1353
+ const int& na,
1354
+ const int& nw,
1355
+ const double& smin,
1356
+ const double& ca,
1357
+ const ap::real_2d_array& a,
1358
+ const double& d1,
1359
+ const double& d2,
1360
+ const ap::real_2d_array& b,
1361
+ const double& wr,
1362
+ const double& wi,
1363
+ ap::boolean_1d_array& rswap4,
1364
+ ap::boolean_1d_array& zswap4,
1365
+ ap::integer_2d_array& ipivot44,
1366
+ ap::real_1d_array& civ4,
1367
+ ap::real_1d_array& crv4,
1368
+ ap::real_2d_array& x,
1369
+ double& scl,
1370
+ double& xnorm,
1371
+ int& info)
1372
+ {
1373
+ int icmax;
1374
+ int j;
1375
+ double bbnd;
1376
+ double bi1;
1377
+ double bi2;
1378
+ double bignum;
1379
+ double bnorm;
1380
+ double br1;
1381
+ double br2;
1382
+ double ci21;
1383
+ double ci22;
1384
+ double cmax;
1385
+ double cnorm;
1386
+ double cr21;
1387
+ double cr22;
1388
+ double csi;
1389
+ double csr;
1390
+ double li21;
1391
+ double lr21;
1392
+ double smini;
1393
+ double smlnum;
1394
+ double temp;
1395
+ double u22abs;
1396
+ double ui11;
1397
+ double ui11r;
1398
+ double ui12;
1399
+ double ui12s;
1400
+ double ui22;
1401
+ double ur11;
1402
+ double ur11r;
1403
+ double ur12;
1404
+ double ur12s;
1405
+ double ur22;
1406
+ double xi1;
1407
+ double xi2;
1408
+ double xr1;
1409
+ double xr2;
1410
+ double tmp1;
1411
+ double tmp2;
1412
+
1413
+ zswap4(1) = false;
1414
+ zswap4(2) = false;
1415
+ zswap4(3) = true;
1416
+ zswap4(4) = true;
1417
+ rswap4(1) = false;
1418
+ rswap4(2) = true;
1419
+ rswap4(3) = false;
1420
+ rswap4(4) = true;
1421
+ ipivot44(1,1) = 1;
1422
+ ipivot44(2,1) = 2;
1423
+ ipivot44(3,1) = 3;
1424
+ ipivot44(4,1) = 4;
1425
+ ipivot44(1,2) = 2;
1426
+ ipivot44(2,2) = 1;
1427
+ ipivot44(3,2) = 4;
1428
+ ipivot44(4,2) = 3;
1429
+ ipivot44(1,3) = 3;
1430
+ ipivot44(2,3) = 4;
1431
+ ipivot44(3,3) = 1;
1432
+ ipivot44(4,3) = 2;
1433
+ ipivot44(1,4) = 4;
1434
+ ipivot44(2,4) = 3;
1435
+ ipivot44(3,4) = 2;
1436
+ ipivot44(4,4) = 1;
1437
+ smlnum = 2*ap::minrealnumber;
1438
+ bignum = 1/smlnum;
1439
+ smini = ap::maxreal(smin, smlnum);
1440
+
1441
+ //
1442
+ // Don't check for input errors
1443
+ //
1444
+ info = 0;
1445
+
1446
+ //
1447
+ // Standard Initializations
1448
+ //
1449
+ scl = 1;
1450
+ if( na==1 )
1451
+ {
1452
+
1453
+ //
1454
+ // 1 x 1 (i.e., scalar) system C X = B
1455
+ //
1456
+ if( nw==1 )
1457
+ {
1458
+
1459
+ //
1460
+ // Real 1x1 system.
1461
+ //
1462
+ // C = ca A - w D
1463
+ //
1464
+ csr = ca*a(1,1)-wr*d1;
1465
+ cnorm = fabs(csr);
1466
+
1467
+ //
1468
+ // If | C | < SMINI, use C = SMINI
1469
+ //
1470
+ if( cnorm<smini )
1471
+ {
1472
+ csr = smini;
1473
+ cnorm = smini;
1474
+ info = 1;
1475
+ }
1476
+
1477
+ //
1478
+ // Check scaling for X = B / C
1479
+ //
1480
+ bnorm = fabs(b(1,1));
1481
+ if( cnorm<1&&bnorm>1 )
1482
+ {
1483
+ if( bnorm>bignum*cnorm )
1484
+ {
1485
+ scl = 1/bnorm;
1486
+ }
1487
+ }
1488
+
1489
+ //
1490
+ // Compute X
1491
+ //
1492
+ x(1,1) = b(1,1)*scl/csr;
1493
+ xnorm = fabs(x(1,1));
1494
+ }
1495
+ else
1496
+ {
1497
+
1498
+ //
1499
+ // Complex 1x1 system (w is complex)
1500
+ //
1501
+ // C = ca A - w D
1502
+ //
1503
+ csr = ca*a(1,1)-wr*d1;
1504
+ csi = -wi*d1;
1505
+ cnorm = fabs(csr)+fabs(csi);
1506
+
1507
+ //
1508
+ // If | C | < SMINI, use C = SMINI
1509
+ //
1510
+ if( cnorm<smini )
1511
+ {
1512
+ csr = smini;
1513
+ csi = 0;
1514
+ cnorm = smini;
1515
+ info = 1;
1516
+ }
1517
+
1518
+ //
1519
+ // Check scaling for X = B / C
1520
+ //
1521
+ bnorm = fabs(b(1,1))+fabs(b(1,2));
1522
+ if( cnorm<1&&bnorm>1 )
1523
+ {
1524
+ if( bnorm>bignum*cnorm )
1525
+ {
1526
+ scl = 1/bnorm;
1527
+ }
1528
+ }
1529
+
1530
+ //
1531
+ // Compute X
1532
+ //
1533
+ internalhsevdladiv(scl*b(1,1), scl*b(1,2), csr, csi, tmp1, tmp2);
1534
+ x(1,1) = tmp1;
1535
+ x(1,2) = tmp2;
1536
+ xnorm = fabs(x(1,1))+fabs(x(1,2));
1537
+ }
1538
+ }
1539
+ else
1540
+ {
1541
+
1542
+ //
1543
+ // 2x2 System
1544
+ //
1545
+ // Compute the real part of C = ca A - w D (or ca A' - w D )
1546
+ //
1547
+ crv4(1+0) = ca*a(1,1)-wr*d1;
1548
+ crv4(2+2) = ca*a(2,2)-wr*d2;
1549
+ if( ltrans )
1550
+ {
1551
+ crv4(1+2) = ca*a(2,1);
1552
+ crv4(2+0) = ca*a(1,2);
1553
+ }
1554
+ else
1555
+ {
1556
+ crv4(2+0) = ca*a(2,1);
1557
+ crv4(1+2) = ca*a(1,2);
1558
+ }
1559
+ if( nw==1 )
1560
+ {
1561
+
1562
+ //
1563
+ // Real 2x2 system (w is real)
1564
+ //
1565
+ // Find the largest element in C
1566
+ //
1567
+ cmax = 0;
1568
+ icmax = 0;
1569
+ for(j = 1; j <= 4; j++)
1570
+ {
1571
+ if( fabs(crv4(j))>cmax )
1572
+ {
1573
+ cmax = fabs(crv4(j));
1574
+ icmax = j;
1575
+ }
1576
+ }
1577
+
1578
+ //
1579
+ // If norm(C) < SMINI, use SMINI*identity.
1580
+ //
1581
+ if( cmax<smini )
1582
+ {
1583
+ bnorm = ap::maxreal(fabs(b(1,1)), fabs(b(2,1)));
1584
+ if( smini<1&&bnorm>1 )
1585
+ {
1586
+ if( bnorm>bignum*smini )
1587
+ {
1588
+ scl = 1/bnorm;
1589
+ }
1590
+ }
1591
+ temp = scl/smini;
1592
+ x(1,1) = temp*b(1,1);
1593
+ x(2,1) = temp*b(2,1);
1594
+ xnorm = temp*bnorm;
1595
+ info = 1;
1596
+ return;
1597
+ }
1598
+
1599
+ //
1600
+ // Gaussian elimination with complete pivoting.
1601
+ //
1602
+ ur11 = crv4(icmax);
1603
+ cr21 = crv4(ipivot44(2,icmax));
1604
+ ur12 = crv4(ipivot44(3,icmax));
1605
+ cr22 = crv4(ipivot44(4,icmax));
1606
+ ur11r = 1/ur11;
1607
+ lr21 = ur11r*cr21;
1608
+ ur22 = cr22-ur12*lr21;
1609
+
1610
+ //
1611
+ // If smaller pivot < SMINI, use SMINI
1612
+ //
1613
+ if( fabs(ur22)<smini )
1614
+ {
1615
+ ur22 = smini;
1616
+ info = 1;
1617
+ }
1618
+ if( rswap4(icmax) )
1619
+ {
1620
+ br1 = b(2,1);
1621
+ br2 = b(1,1);
1622
+ }
1623
+ else
1624
+ {
1625
+ br1 = b(1,1);
1626
+ br2 = b(2,1);
1627
+ }
1628
+ br2 = br2-lr21*br1;
1629
+ bbnd = ap::maxreal(fabs(br1*(ur22*ur11r)), fabs(br2));
1630
+ if( bbnd>1&&fabs(ur22)<1 )
1631
+ {
1632
+ if( bbnd>=bignum*fabs(ur22) )
1633
+ {
1634
+ scl = 1/bbnd;
1635
+ }
1636
+ }
1637
+ xr2 = br2*scl/ur22;
1638
+ xr1 = scl*br1*ur11r-xr2*(ur11r*ur12);
1639
+ if( zswap4(icmax) )
1640
+ {
1641
+ x(1,1) = xr2;
1642
+ x(2,1) = xr1;
1643
+ }
1644
+ else
1645
+ {
1646
+ x(1,1) = xr1;
1647
+ x(2,1) = xr2;
1648
+ }
1649
+ xnorm = ap::maxreal(fabs(xr1), fabs(xr2));
1650
+
1651
+ //
1652
+ // Further scaling if norm(A) norm(X) > overflow
1653
+ //
1654
+ if( xnorm>1&&cmax>1 )
1655
+ {
1656
+ if( xnorm>bignum/cmax )
1657
+ {
1658
+ temp = cmax/bignum;
1659
+ x(1,1) = temp*x(1,1);
1660
+ x(2,1) = temp*x(2,1);
1661
+ xnorm = temp*xnorm;
1662
+ scl = temp*scl;
1663
+ }
1664
+ }
1665
+ }
1666
+ else
1667
+ {
1668
+
1669
+ //
1670
+ // Complex 2x2 system (w is complex)
1671
+ //
1672
+ // Find the largest element in C
1673
+ //
1674
+ civ4(1+0) = -wi*d1;
1675
+ civ4(2+0) = 0;
1676
+ civ4(1+2) = 0;
1677
+ civ4(2+2) = -wi*d2;
1678
+ cmax = 0;
1679
+ icmax = 0;
1680
+ for(j = 1; j <= 4; j++)
1681
+ {
1682
+ if( fabs(crv4(j))+fabs(civ4(j))>cmax )
1683
+ {
1684
+ cmax = fabs(crv4(j))+fabs(civ4(j));
1685
+ icmax = j;
1686
+ }
1687
+ }
1688
+
1689
+ //
1690
+ // If norm(C) < SMINI, use SMINI*identity.
1691
+ //
1692
+ if( cmax<smini )
1693
+ {
1694
+ bnorm = ap::maxreal(fabs(b(1,1))+fabs(b(1,2)), fabs(b(2,1))+fabs(b(2,2)));
1695
+ if( smini<1&&bnorm>1 )
1696
+ {
1697
+ if( bnorm>bignum*smini )
1698
+ {
1699
+ scl = 1/bnorm;
1700
+ }
1701
+ }
1702
+ temp = scl/smini;
1703
+ x(1,1) = temp*b(1,1);
1704
+ x(2,1) = temp*b(2,1);
1705
+ x(1,2) = temp*b(1,2);
1706
+ x(2,2) = temp*b(2,2);
1707
+ xnorm = temp*bnorm;
1708
+ info = 1;
1709
+ return;
1710
+ }
1711
+
1712
+ //
1713
+ // Gaussian elimination with complete pivoting.
1714
+ //
1715
+ ur11 = crv4(icmax);
1716
+ ui11 = civ4(icmax);
1717
+ cr21 = crv4(ipivot44(2,icmax));
1718
+ ci21 = civ4(ipivot44(2,icmax));
1719
+ ur12 = crv4(ipivot44(3,icmax));
1720
+ ui12 = civ4(ipivot44(3,icmax));
1721
+ cr22 = crv4(ipivot44(4,icmax));
1722
+ ci22 = civ4(ipivot44(4,icmax));
1723
+ if( icmax==1||icmax==4 )
1724
+ {
1725
+
1726
+ //
1727
+ // Code when off-diagonals of pivoted C are real
1728
+ //
1729
+ if( fabs(ur11)>fabs(ui11) )
1730
+ {
1731
+ temp = ui11/ur11;
1732
+ ur11r = 1/(ur11*(1+ap::sqr(temp)));
1733
+ ui11r = -temp*ur11r;
1734
+ }
1735
+ else
1736
+ {
1737
+ temp = ur11/ui11;
1738
+ ui11r = -1/(ui11*(1+ap::sqr(temp)));
1739
+ ur11r = -temp*ui11r;
1740
+ }
1741
+ lr21 = cr21*ur11r;
1742
+ li21 = cr21*ui11r;
1743
+ ur12s = ur12*ur11r;
1744
+ ui12s = ur12*ui11r;
1745
+ ur22 = cr22-ur12*lr21;
1746
+ ui22 = ci22-ur12*li21;
1747
+ }
1748
+ else
1749
+ {
1750
+
1751
+ //
1752
+ // Code when diagonals of pivoted C are real
1753
+ //
1754
+ ur11r = 1/ur11;
1755
+ ui11r = 0;
1756
+ lr21 = cr21*ur11r;
1757
+ li21 = ci21*ur11r;
1758
+ ur12s = ur12*ur11r;
1759
+ ui12s = ui12*ur11r;
1760
+ ur22 = cr22-ur12*lr21+ui12*li21;
1761
+ ui22 = -ur12*li21-ui12*lr21;
1762
+ }
1763
+ u22abs = fabs(ur22)+fabs(ui22);
1764
+
1765
+ //
1766
+ // If smaller pivot < SMINI, use SMINI
1767
+ //
1768
+ if( u22abs<smini )
1769
+ {
1770
+ ur22 = smini;
1771
+ ui22 = 0;
1772
+ info = 1;
1773
+ }
1774
+ if( rswap4(icmax) )
1775
+ {
1776
+ br2 = b(1,1);
1777
+ br1 = b(2,1);
1778
+ bi2 = b(1,2);
1779
+ bi1 = b(2,2);
1780
+ }
1781
+ else
1782
+ {
1783
+ br1 = b(1,1);
1784
+ br2 = b(2,1);
1785
+ bi1 = b(1,2);
1786
+ bi2 = b(2,2);
1787
+ }
1788
+ br2 = br2-lr21*br1+li21*bi1;
1789
+ bi2 = bi2-li21*br1-lr21*bi1;
1790
+ bbnd = ap::maxreal((fabs(br1)+fabs(bi1))*(u22abs*(fabs(ur11r)+fabs(ui11r))), fabs(br2)+fabs(bi2));
1791
+ if( bbnd>1&&u22abs<1 )
1792
+ {
1793
+ if( bbnd>=bignum*u22abs )
1794
+ {
1795
+ scl = 1/bbnd;
1796
+ br1 = scl*br1;
1797
+ bi1 = scl*bi1;
1798
+ br2 = scl*br2;
1799
+ bi2 = scl*bi2;
1800
+ }
1801
+ }
1802
+ internalhsevdladiv(br2, bi2, ur22, ui22, xr2, xi2);
1803
+ xr1 = ur11r*br1-ui11r*bi1-ur12s*xr2+ui12s*xi2;
1804
+ xi1 = ui11r*br1+ur11r*bi1-ui12s*xr2-ur12s*xi2;
1805
+ if( zswap4(icmax) )
1806
+ {
1807
+ x(1,1) = xr2;
1808
+ x(2,1) = xr1;
1809
+ x(1,2) = xi2;
1810
+ x(2,2) = xi1;
1811
+ }
1812
+ else
1813
+ {
1814
+ x(1,1) = xr1;
1815
+ x(2,1) = xr2;
1816
+ x(1,2) = xi1;
1817
+ x(2,2) = xi2;
1818
+ }
1819
+ xnorm = ap::maxreal(fabs(xr1)+fabs(xi1), fabs(xr2)+fabs(xi2));
1820
+
1821
+ //
1822
+ // Further scaling if norm(A) norm(X) > overflow
1823
+ //
1824
+ if( xnorm>1&&cmax>1 )
1825
+ {
1826
+ if( xnorm>bignum/cmax )
1827
+ {
1828
+ temp = cmax/bignum;
1829
+ x(1,1) = temp*x(1,1);
1830
+ x(2,1) = temp*x(2,1);
1831
+ x(1,2) = temp*x(1,2);
1832
+ x(2,2) = temp*x(2,2);
1833
+ xnorm = temp*xnorm;
1834
+ scl = temp*scl;
1835
+ }
1836
+ }
1837
+ }
1838
+ }
1839
+ }
1840
+
1841
+
1842
+ static void internalhsevdladiv(const double& a,
1843
+ const double& b,
1844
+ const double& c,
1845
+ const double& d,
1846
+ double& p,
1847
+ double& q)
1848
+ {
1849
+ double e;
1850
+ double f;
1851
+
1852
+ if( fabs(d)<fabs(c) )
1853
+ {
1854
+ e = d/c;
1855
+ f = c+d*e;
1856
+ p = (a+b*e)/f;
1857
+ q = (b-a*e)/f;
1858
+ }
1859
+ else
1860
+ {
1861
+ e = c/d;
1862
+ f = d+c*e;
1863
+ p = (b+a*e)/f;
1864
+ q = (-a+b*e)/f;
1865
+ }
1866
+ }
1867
+
1868
+
1869
+