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,126 @@
1
+ /*************************************************************************
2
+ Copyright (c) 2005-2007, Sergey Bochkanov (ALGLIB project).
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions are
6
+ met:
7
+
8
+ - Redistributions of source code must retain the above copyright
9
+ notice, this list of conditions and the following disclaimer.
10
+
11
+ - Redistributions in binary form must reproduce the above copyright
12
+ notice, this list of conditions and the following disclaimer listed
13
+ in this license in the documentation and/or other materials
14
+ provided with the distribution.
15
+
16
+ - Neither the name of the copyright holders nor the names of its
17
+ contributors may be used to endorse or promote products derived from
18
+ this software without specific prior written permission.
19
+
20
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
+ *************************************************************************/
32
+
33
+ #ifndef _svd_h
34
+ #define _svd_h
35
+
36
+ #include "ap.h"
37
+ #include "ialglib.h"
38
+
39
+ #include "reflections.h"
40
+ #include "bidiagonal.h"
41
+ #include "qr.h"
42
+ #include "lq.h"
43
+ #include "blas.h"
44
+ #include "rotations.h"
45
+ #include "bdsvd.h"
46
+
47
+
48
+ /*************************************************************************
49
+ Singular value decomposition of a rectangular matrix.
50
+
51
+ The algorithm calculates the singular value decomposition of a matrix of
52
+ size MxN: A = U * S * V^T
53
+
54
+ The algorithm finds the singular values and, optionally, matrices U and V^T.
55
+ The algorithm can find both first min(M,N) columns of matrix U and rows of
56
+ matrix V^T (singular vectors), and matrices U and V^T wholly (of sizes MxM
57
+ and NxN respectively).
58
+
59
+ Take into account that the subroutine does not return matrix V but V^T.
60
+
61
+ Input parameters:
62
+ A - matrix to be decomposed.
63
+ Array whose indexes range within [0..M-1, 0..N-1].
64
+ M - number of rows in matrix A.
65
+ N - number of columns in matrix A.
66
+ UNeeded - 0, 1 or 2. See the description of the parameter U.
67
+ VTNeeded - 0, 1 or 2. See the description of the parameter VT.
68
+ AdditionalMemory -
69
+ If the parameter:
70
+ * equals 0, the algorithm doesn�t use additional
71
+ memory (lower requirements, lower performance).
72
+ * equals 1, the algorithm uses additional
73
+ memory of size min(M,N)*min(M,N) of real numbers.
74
+ It often speeds up the algorithm.
75
+ * equals 2, the algorithm uses additional
76
+ memory of size M*min(M,N) of real numbers.
77
+ It allows to get a maximum performance.
78
+ The recommended value of the parameter is 2.
79
+
80
+ Output parameters:
81
+ W - contains singular values in descending order.
82
+ U - if UNeeded=0, U isn't changed, the left singular vectors
83
+ are not calculated.
84
+ if Uneeded=1, U contains left singular vectors (first
85
+ min(M,N) columns of matrix U). Array whose indexes range
86
+ within [0..M-1, 0..Min(M,N)-1].
87
+ if UNeeded=2, U contains matrix U wholly. Array whose
88
+ indexes range within [0..M-1, 0..M-1].
89
+ VT - if VTNeeded=0, VT isn�t changed, the right singular vectors
90
+ are not calculated.
91
+ if VTNeeded=1, VT contains right singular vectors (first
92
+ min(M,N) rows of matrix V^T). Array whose indexes range
93
+ within [0..min(M,N)-1, 0..N-1].
94
+ if VTNeeded=2, VT contains matrix V^T wholly. Array whose
95
+ indexes range within [0..N-1, 0..N-1].
96
+
97
+ -- ALGLIB --
98
+ Copyright 2005 by Bochkanov Sergey
99
+ *************************************************************************/
100
+ bool rmatrixsvd(ap::real_2d_array a,
101
+ int m,
102
+ int n,
103
+ int uneeded,
104
+ int vtneeded,
105
+ int additionalmemory,
106
+ ap::real_1d_array& w,
107
+ ap::real_2d_array& u,
108
+ ap::real_2d_array& vt);
109
+
110
+
111
+ /*************************************************************************
112
+ Obsolete 1-based subroutine.
113
+ See RMatrixSVD for 0-based replacement.
114
+ *************************************************************************/
115
+ bool svddecomposition(ap::real_2d_array a,
116
+ int m,
117
+ int n,
118
+ int uneeded,
119
+ int vtneeded,
120
+ int additionalmemory,
121
+ ap::real_1d_array& w,
122
+ ap::real_2d_array& u,
123
+ ap::real_2d_array& vt);
124
+
125
+
126
+ #endif
@@ -0,0 +1,2608 @@
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 "tdbisinv.h"
41
+
42
+ static void tdininternaldlagtf(const int& n,
43
+ ap::real_1d_array& a,
44
+ const double& lambda,
45
+ ap::real_1d_array& b,
46
+ ap::real_1d_array& c,
47
+ const double& tol,
48
+ ap::real_1d_array& d,
49
+ ap::integer_1d_array& iin,
50
+ int& info);
51
+ static void tdininternaldlagts(const int& n,
52
+ const ap::real_1d_array& a,
53
+ const ap::real_1d_array& b,
54
+ const ap::real_1d_array& c,
55
+ const ap::real_1d_array& d,
56
+ const ap::integer_1d_array& iin,
57
+ ap::real_1d_array& y,
58
+ double& tol,
59
+ int& info);
60
+ static void internaldlaebz(const int& ijob,
61
+ const int& nitmax,
62
+ const int& n,
63
+ const int& mmax,
64
+ const int& minp,
65
+ const double& abstol,
66
+ const double& reltol,
67
+ const double& pivmin,
68
+ const ap::real_1d_array& d,
69
+ const ap::real_1d_array& e,
70
+ const ap::real_1d_array& e2,
71
+ ap::integer_1d_array& nval,
72
+ ap::real_2d_array& ab,
73
+ ap::real_1d_array& c,
74
+ int& mout,
75
+ ap::integer_2d_array& nab,
76
+ ap::real_1d_array& work,
77
+ ap::integer_1d_array& iwork,
78
+ int& info);
79
+
80
+ /*************************************************************************
81
+ Subroutine for finding the tridiagonal matrix eigenvalues/vectors in a
82
+ given half-interval (A, B] by using bisection and inverse iteration.
83
+
84
+ Input parameters:
85
+ D - the main diagonal of a tridiagonal matrix.
86
+ Array whose index ranges within [0..N-1].
87
+ E - the secondary diagonal of a tridiagonal matrix.
88
+ Array whose index ranges within [0..N-2].
89
+ N - size of matrix, N>=0.
90
+ ZNeeded - flag controlling whether the eigenvectors are needed or not.
91
+ If ZNeeded is equal to:
92
+ * 0, the eigenvectors are not needed;
93
+ * 1, the eigenvectors of a tridiagonal matrix are multiplied
94
+ by the square matrix Z. It is used if the tridiagonal
95
+ matrix is obtained by the similarity transformation
96
+ of a symmetric matrix.
97
+ * 2, the eigenvectors of a tridiagonal matrix replace matrix Z.
98
+ A, B - half-interval (A, B] to search eigenvalues in.
99
+ Z - if ZNeeded is equal to:
100
+ * 0, Z isn't used and remains unchanged;
101
+ * 1, Z contains the square matrix (array whose indexes range
102
+ within [0..N-1, 0..N-1]) which reduces the given symmetric
103
+ matrix to tridiagonal form;
104
+ * 2, Z isn't used (but changed on the exit).
105
+
106
+ Output parameters:
107
+ D - array of the eigenvalues found.
108
+ Array whose index ranges within [0..M-1].
109
+ M - number of eigenvalues found in the given half-interval (M>=0).
110
+ Z - if ZNeeded is equal to:
111
+ * 0, doesn't contain any information;
112
+ * 1, contains the product of a given NxN matrix Z (from the
113
+ left) and NxM matrix of the eigenvectors found (from the
114
+ right). Array whose indexes range within [0..N-1, 0..M-1].
115
+ * 2, contains the matrix of the eigenvectors found.
116
+ Array whose indexes range within [0..N-1, 0..M-1].
117
+
118
+ Result:
119
+
120
+ True, if successful. In that case, M contains the number of eigenvalues
121
+ in the given half-interval (could be equal to 0), D contains the eigenvalues,
122
+ Z contains the eigenvectors (if needed).
123
+ It should be noted that the subroutine changes the size of arrays D and Z.
124
+
125
+ False, if the bisection method subroutine wasn't able to find the
126
+ eigenvalues in the given interval or if the inverse iteration subroutine
127
+ wasn't able to find all the corresponding eigenvectors. In that case,
128
+ the eigenvalues and eigenvectors are not returned, M is equal to 0.
129
+
130
+ -- ALGLIB --
131
+ Copyright 31.03.2008 by Bochkanov Sergey
132
+ *************************************************************************/
133
+ bool smatrixtdevdr(ap::real_1d_array& d,
134
+ const ap::real_1d_array& e,
135
+ int n,
136
+ int zneeded,
137
+ double a,
138
+ double b,
139
+ int& m,
140
+ ap::real_2d_array& z)
141
+ {
142
+ bool result;
143
+ int errorcode;
144
+ int nsplit;
145
+ int i;
146
+ int j;
147
+ int k;
148
+ int cr;
149
+ ap::integer_1d_array iblock;
150
+ ap::integer_1d_array isplit;
151
+ ap::integer_1d_array ifail;
152
+ ap::real_1d_array d1;
153
+ ap::real_1d_array e1;
154
+ ap::real_1d_array w;
155
+ ap::real_2d_array z2;
156
+ ap::real_2d_array z3;
157
+ double v;
158
+
159
+ ap::ap_error::make_assertion(zneeded>=0&&zneeded<=2, "SMatrixTDEVDR: incorrect ZNeeded!");
160
+
161
+ //
162
+ // Special cases
163
+ //
164
+ if( b<=a )
165
+ {
166
+ m = 0;
167
+ result = true;
168
+ return result;
169
+ }
170
+ if( n<=0 )
171
+ {
172
+ m = 0;
173
+ result = true;
174
+ return result;
175
+ }
176
+
177
+ //
178
+ // Copy D,E to D1, E1
179
+ //
180
+ d1.setbounds(1, n);
181
+ ap::vmove(&d1(1), &d(0), ap::vlen(1,n));
182
+ if( n>1 )
183
+ {
184
+ e1.setbounds(1, n-1);
185
+ ap::vmove(&e1(1), &e(0), ap::vlen(1,n-1));
186
+ }
187
+
188
+ //
189
+ // No eigen vectors
190
+ //
191
+ if( zneeded==0 )
192
+ {
193
+ result = internalbisectioneigenvalues(d1, e1, n, 2, 1, a, b, 0, 0, double(-1), w, m, nsplit, iblock, isplit, errorcode);
194
+ if( !result||m==0 )
195
+ {
196
+ m = 0;
197
+ return result;
198
+ }
199
+ d.setbounds(0, m-1);
200
+ ap::vmove(&d(0), &w(1), ap::vlen(0,m-1));
201
+ return result;
202
+ }
203
+
204
+ //
205
+ // Eigen vectors are multiplied by Z
206
+ //
207
+ if( zneeded==1 )
208
+ {
209
+
210
+ //
211
+ // Find eigen pairs
212
+ //
213
+ result = internalbisectioneigenvalues(d1, e1, n, 2, 2, a, b, 0, 0, double(-1), w, m, nsplit, iblock, isplit, errorcode);
214
+ if( !result||m==0 )
215
+ {
216
+ m = 0;
217
+ return result;
218
+ }
219
+ internaldstein(n, d1, e1, m, w, iblock, isplit, z2, ifail, cr);
220
+ if( cr!=0 )
221
+ {
222
+ m = 0;
223
+ result = false;
224
+ return result;
225
+ }
226
+
227
+ //
228
+ // Sort eigen values and vectors
229
+ //
230
+ for(i = 1; i <= m; i++)
231
+ {
232
+ k = i;
233
+ for(j = i; j <= m; j++)
234
+ {
235
+ if( w(j)<w(k) )
236
+ {
237
+ k = j;
238
+ }
239
+ }
240
+ v = w(i);
241
+ w(i) = w(k);
242
+ w(k) = v;
243
+ for(j = 1; j <= n; j++)
244
+ {
245
+ v = z2(j,i);
246
+ z2(j,i) = z2(j,k);
247
+ z2(j,k) = v;
248
+ }
249
+ }
250
+
251
+ //
252
+ // Transform Z2 and overwrite Z
253
+ //
254
+ z3.setbounds(1, m, 1, n);
255
+ for(i = 1; i <= m; i++)
256
+ {
257
+ ap::vmove(z3.getrow(i, 1, n), z2.getcolumn(i, 1, n));
258
+ }
259
+ for(i = 1; i <= n; i++)
260
+ {
261
+ for(j = 1; j <= m; j++)
262
+ {
263
+ v = ap::vdotproduct(&z(i-1, 0), &z3(j, 1), ap::vlen(0,n-1));
264
+ z2(i,j) = v;
265
+ }
266
+ }
267
+ z.setbounds(0, n-1, 0, m-1);
268
+ for(i = 1; i <= m; i++)
269
+ {
270
+ ap::vmove(z.getcolumn(i-1, 0, n-1), z2.getcolumn(i, 1, n));
271
+ }
272
+
273
+ //
274
+ // Store W
275
+ //
276
+ d.setbounds(0, m-1);
277
+ for(i = 1; i <= m; i++)
278
+ {
279
+ d(i-1) = w(i);
280
+ }
281
+ return result;
282
+ }
283
+
284
+ //
285
+ // Eigen vectors are stored in Z
286
+ //
287
+ if( zneeded==2 )
288
+ {
289
+
290
+ //
291
+ // Find eigen pairs
292
+ //
293
+ result = internalbisectioneigenvalues(d1, e1, n, 2, 2, a, b, 0, 0, double(-1), w, m, nsplit, iblock, isplit, errorcode);
294
+ if( !result||m==0 )
295
+ {
296
+ m = 0;
297
+ return result;
298
+ }
299
+ internaldstein(n, d1, e1, m, w, iblock, isplit, z2, ifail, cr);
300
+ if( cr!=0 )
301
+ {
302
+ m = 0;
303
+ result = false;
304
+ return result;
305
+ }
306
+
307
+ //
308
+ // Sort eigen values and vectors
309
+ //
310
+ for(i = 1; i <= m; i++)
311
+ {
312
+ k = i;
313
+ for(j = i; j <= m; j++)
314
+ {
315
+ if( w(j)<w(k) )
316
+ {
317
+ k = j;
318
+ }
319
+ }
320
+ v = w(i);
321
+ w(i) = w(k);
322
+ w(k) = v;
323
+ for(j = 1; j <= n; j++)
324
+ {
325
+ v = z2(j,i);
326
+ z2(j,i) = z2(j,k);
327
+ z2(j,k) = v;
328
+ }
329
+ }
330
+
331
+ //
332
+ // Store W
333
+ //
334
+ d.setbounds(0, m-1);
335
+ for(i = 1; i <= m; i++)
336
+ {
337
+ d(i-1) = w(i);
338
+ }
339
+ z.setbounds(0, n-1, 0, m-1);
340
+ for(i = 1; i <= m; i++)
341
+ {
342
+ ap::vmove(z.getcolumn(i-1, 0, n-1), z2.getcolumn(i, 1, n));
343
+ }
344
+ return result;
345
+ }
346
+ result = false;
347
+ return result;
348
+ }
349
+
350
+
351
+ /*************************************************************************
352
+ Subroutine for finding tridiagonal matrix eigenvalues/vectors with given
353
+ indexes (in ascending order) by using the bisection and inverse iteraion.
354
+
355
+ Input parameters:
356
+ D - the main diagonal of a tridiagonal matrix.
357
+ Array whose index ranges within [0..N-1].
358
+ E - the secondary diagonal of a tridiagonal matrix.
359
+ Array whose index ranges within [0..N-2].
360
+ N - size of matrix. N>=0.
361
+ ZNeeded - flag controlling whether the eigenvectors are needed or not.
362
+ If ZNeeded is equal to:
363
+ * 0, the eigenvectors are not needed;
364
+ * 1, the eigenvectors of a tridiagonal matrix are multiplied
365
+ by the square matrix Z. It is used if the
366
+ tridiagonal matrix is obtained by the similarity transformation
367
+ of a symmetric matrix.
368
+ * 2, the eigenvectors of a tridiagonal matrix replace
369
+ matrix Z.
370
+ I1, I2 - index interval for searching (from I1 to I2).
371
+ 0 <= I1 <= I2 <= N-1.
372
+ Z - if ZNeeded is equal to:
373
+ * 0, Z isn't used and remains unchanged;
374
+ * 1, Z contains the square matrix (array whose indexes range within [0..N-1, 0..N-1])
375
+ which reduces the given symmetric matrix to tridiagonal form;
376
+ * 2, Z isn't used (but changed on the exit).
377
+
378
+ Output parameters:
379
+ D - array of the eigenvalues found.
380
+ Array whose index ranges within [0..I2-I1].
381
+ Z - if ZNeeded is equal to:
382
+ * 0, doesn't contain any information;
383
+ * 1, contains the product of a given NxN matrix Z (from the left) and
384
+ Nx(I2-I1) matrix of the eigenvectors found (from the right).
385
+ Array whose indexes range within [0..N-1, 0..I2-I1].
386
+ * 2, contains the matrix of the eigenvalues found.
387
+ Array whose indexes range within [0..N-1, 0..I2-I1].
388
+
389
+
390
+ Result:
391
+
392
+ True, if successful. In that case, D contains the eigenvalues,
393
+ Z contains the eigenvectors (if needed).
394
+ It should be noted that the subroutine changes the size of arrays D and Z.
395
+
396
+ False, if the bisection method subroutine wasn't able to find the eigenvalues
397
+ in the given interval or if the inverse iteration subroutine wasn't able
398
+ to find all the corresponding eigenvectors. In that case, the eigenvalues
399
+ and eigenvectors are not returned.
400
+
401
+ -- ALGLIB --
402
+ Copyright 25.12.2005 by Bochkanov Sergey
403
+ *************************************************************************/
404
+ bool smatrixtdevdi(ap::real_1d_array& d,
405
+ const ap::real_1d_array& e,
406
+ int n,
407
+ int zneeded,
408
+ int i1,
409
+ int i2,
410
+ ap::real_2d_array& z)
411
+ {
412
+ bool result;
413
+ int errorcode;
414
+ int nsplit;
415
+ int i;
416
+ int j;
417
+ int k;
418
+ int m;
419
+ int cr;
420
+ ap::integer_1d_array iblock;
421
+ ap::integer_1d_array isplit;
422
+ ap::integer_1d_array ifail;
423
+ ap::real_1d_array w;
424
+ ap::real_1d_array d1;
425
+ ap::real_1d_array e1;
426
+ ap::real_2d_array z2;
427
+ ap::real_2d_array z3;
428
+ double v;
429
+
430
+ ap::ap_error::make_assertion(0<=i1&&i1<=i2&&i2<n, "SMatrixTDEVDI: incorrect I1/I2!");
431
+
432
+ //
433
+ // Copy D,E to D1, E1
434
+ //
435
+ d1.setbounds(1, n);
436
+ ap::vmove(&d1(1), &d(0), ap::vlen(1,n));
437
+ if( n>1 )
438
+ {
439
+ e1.setbounds(1, n-1);
440
+ ap::vmove(&e1(1), &e(0), ap::vlen(1,n-1));
441
+ }
442
+
443
+ //
444
+ // No eigen vectors
445
+ //
446
+ if( zneeded==0 )
447
+ {
448
+ result = internalbisectioneigenvalues(d1, e1, n, 3, 1, double(0), double(0), i1+1, i2+1, double(-1), w, m, nsplit, iblock, isplit, errorcode);
449
+ if( !result )
450
+ {
451
+ return result;
452
+ }
453
+ if( m!=i2-i1+1 )
454
+ {
455
+ result = false;
456
+ return result;
457
+ }
458
+ d.setbounds(0, m-1);
459
+ for(i = 1; i <= m; i++)
460
+ {
461
+ d(i-1) = w(i);
462
+ }
463
+ return result;
464
+ }
465
+
466
+ //
467
+ // Eigen vectors are multiplied by Z
468
+ //
469
+ if( zneeded==1 )
470
+ {
471
+
472
+ //
473
+ // Find eigen pairs
474
+ //
475
+ result = internalbisectioneigenvalues(d1, e1, n, 3, 2, double(0), double(0), i1+1, i2+1, double(-1), w, m, nsplit, iblock, isplit, errorcode);
476
+ if( !result )
477
+ {
478
+ return result;
479
+ }
480
+ if( m!=i2-i1+1 )
481
+ {
482
+ result = false;
483
+ return result;
484
+ }
485
+ internaldstein(n, d1, e1, m, w, iblock, isplit, z2, ifail, cr);
486
+ if( cr!=0 )
487
+ {
488
+ result = false;
489
+ return result;
490
+ }
491
+
492
+ //
493
+ // Sort eigen values and vectors
494
+ //
495
+ for(i = 1; i <= m; i++)
496
+ {
497
+ k = i;
498
+ for(j = i; j <= m; j++)
499
+ {
500
+ if( w(j)<w(k) )
501
+ {
502
+ k = j;
503
+ }
504
+ }
505
+ v = w(i);
506
+ w(i) = w(k);
507
+ w(k) = v;
508
+ for(j = 1; j <= n; j++)
509
+ {
510
+ v = z2(j,i);
511
+ z2(j,i) = z2(j,k);
512
+ z2(j,k) = v;
513
+ }
514
+ }
515
+
516
+ //
517
+ // Transform Z2 and overwrite Z
518
+ //
519
+ z3.setbounds(1, m, 1, n);
520
+ for(i = 1; i <= m; i++)
521
+ {
522
+ ap::vmove(z3.getrow(i, 1, n), z2.getcolumn(i, 1, n));
523
+ }
524
+ for(i = 1; i <= n; i++)
525
+ {
526
+ for(j = 1; j <= m; j++)
527
+ {
528
+ v = ap::vdotproduct(&z(i-1, 0), &z3(j, 1), ap::vlen(0,n-1));
529
+ z2(i,j) = v;
530
+ }
531
+ }
532
+ z.setbounds(0, n-1, 0, m-1);
533
+ for(i = 1; i <= m; i++)
534
+ {
535
+ ap::vmove(z.getcolumn(i-1, 0, n-1), z2.getcolumn(i, 1, n));
536
+ }
537
+
538
+ //
539
+ // Store W
540
+ //
541
+ d.setbounds(0, m-1);
542
+ for(i = 1; i <= m; i++)
543
+ {
544
+ d(i-1) = w(i);
545
+ }
546
+ return result;
547
+ }
548
+
549
+ //
550
+ // Eigen vectors are stored in Z
551
+ //
552
+ if( zneeded==2 )
553
+ {
554
+
555
+ //
556
+ // Find eigen pairs
557
+ //
558
+ result = internalbisectioneigenvalues(d1, e1, n, 3, 2, double(0), double(0), i1+1, i2+1, double(-1), w, m, nsplit, iblock, isplit, errorcode);
559
+ if( !result )
560
+ {
561
+ return result;
562
+ }
563
+ if( m!=i2-i1+1 )
564
+ {
565
+ result = false;
566
+ return result;
567
+ }
568
+ internaldstein(n, d1, e1, m, w, iblock, isplit, z2, ifail, cr);
569
+ if( cr!=0 )
570
+ {
571
+ result = false;
572
+ return result;
573
+ }
574
+
575
+ //
576
+ // Sort eigen values and vectors
577
+ //
578
+ for(i = 1; i <= m; i++)
579
+ {
580
+ k = i;
581
+ for(j = i; j <= m; j++)
582
+ {
583
+ if( w(j)<w(k) )
584
+ {
585
+ k = j;
586
+ }
587
+ }
588
+ v = w(i);
589
+ w(i) = w(k);
590
+ w(k) = v;
591
+ for(j = 1; j <= n; j++)
592
+ {
593
+ v = z2(j,i);
594
+ z2(j,i) = z2(j,k);
595
+ z2(j,k) = v;
596
+ }
597
+ }
598
+
599
+ //
600
+ // Store Z
601
+ //
602
+ z.setbounds(0, n-1, 0, m-1);
603
+ for(i = 1; i <= m; i++)
604
+ {
605
+ ap::vmove(z.getcolumn(i-1, 0, n-1), z2.getcolumn(i, 1, n));
606
+ }
607
+
608
+ //
609
+ // Store W
610
+ //
611
+ d.setbounds(0, m-1);
612
+ for(i = 1; i <= m; i++)
613
+ {
614
+ d(i-1) = w(i);
615
+ }
616
+ return result;
617
+ }
618
+ result = false;
619
+ return result;
620
+ }
621
+
622
+
623
+ /*************************************************************************
624
+ Obsolete 1-based subroutine
625
+ *************************************************************************/
626
+ bool tridiagonaleigenvaluesandvectorsininterval(ap::real_1d_array& d,
627
+ const ap::real_1d_array& e,
628
+ int n,
629
+ int zneeded,
630
+ double a,
631
+ double b,
632
+ int& m,
633
+ ap::real_2d_array& z)
634
+ {
635
+ bool result;
636
+ int errorcode;
637
+ int nsplit;
638
+ int i;
639
+ int j;
640
+ int k;
641
+ int cr;
642
+ ap::integer_1d_array iblock;
643
+ ap::integer_1d_array isplit;
644
+ ap::integer_1d_array ifail;
645
+ ap::real_1d_array w;
646
+ ap::real_2d_array z2;
647
+ ap::real_2d_array z3;
648
+ double v;
649
+
650
+
651
+ //
652
+ // No eigen vectors
653
+ //
654
+ if( zneeded==0 )
655
+ {
656
+ result = internalbisectioneigenvalues(d, e, n, 2, 1, a, b, 0, 0, double(-1), w, m, nsplit, iblock, isplit, errorcode);
657
+ if( !result||m==0 )
658
+ {
659
+ m = 0;
660
+ return result;
661
+ }
662
+ d.setbounds(1, m);
663
+ for(i = 1; i <= m; i++)
664
+ {
665
+ d(i) = w(i);
666
+ }
667
+ return result;
668
+ }
669
+
670
+ //
671
+ // Eigen vectors are multiplied by Z
672
+ //
673
+ if( zneeded==1 )
674
+ {
675
+
676
+ //
677
+ // Find eigen pairs
678
+ //
679
+ result = internalbisectioneigenvalues(d, e, n, 2, 2, a, b, 0, 0, double(-1), w, m, nsplit, iblock, isplit, errorcode);
680
+ if( !result||m==0 )
681
+ {
682
+ m = 0;
683
+ return result;
684
+ }
685
+ internaldstein(n, d, e, m, w, iblock, isplit, z2, ifail, cr);
686
+ if( cr!=0 )
687
+ {
688
+ m = 0;
689
+ result = false;
690
+ return result;
691
+ }
692
+
693
+ //
694
+ // Sort eigen values and vectors
695
+ //
696
+ for(i = 1; i <= m; i++)
697
+ {
698
+ k = i;
699
+ for(j = i; j <= m; j++)
700
+ {
701
+ if( w(j)<w(k) )
702
+ {
703
+ k = j;
704
+ }
705
+ }
706
+ v = w(i);
707
+ w(i) = w(k);
708
+ w(k) = v;
709
+ for(j = 1; j <= n; j++)
710
+ {
711
+ v = z2(j,i);
712
+ z2(j,i) = z2(j,k);
713
+ z2(j,k) = v;
714
+ }
715
+ }
716
+
717
+ //
718
+ // Transform Z2 and overwrite Z
719
+ //
720
+ z3.setbounds(1, m, 1, n);
721
+ for(i = 1; i <= m; i++)
722
+ {
723
+ ap::vmove(z3.getrow(i, 1, n), z2.getcolumn(i, 1, n));
724
+ }
725
+ for(i = 1; i <= n; i++)
726
+ {
727
+ for(j = 1; j <= m; j++)
728
+ {
729
+ v = ap::vdotproduct(&z(i, 1), &z3(j, 1), ap::vlen(1,n));
730
+ z2(i,j) = v;
731
+ }
732
+ }
733
+ z.setbounds(1, n, 1, m);
734
+ for(i = 1; i <= m; i++)
735
+ {
736
+ ap::vmove(z.getcolumn(i, 1, n), z2.getcolumn(i, 1, n));
737
+ }
738
+
739
+ //
740
+ // Store W
741
+ //
742
+ d.setbounds(1, m);
743
+ for(i = 1; i <= m; i++)
744
+ {
745
+ d(i) = w(i);
746
+ }
747
+ return result;
748
+ }
749
+
750
+ //
751
+ // Eigen vectors are stored in Z
752
+ //
753
+ if( zneeded==2 )
754
+ {
755
+
756
+ //
757
+ // Find eigen pairs
758
+ //
759
+ result = internalbisectioneigenvalues(d, e, n, 2, 2, a, b, 0, 0, double(-1), w, m, nsplit, iblock, isplit, errorcode);
760
+ if( !result||m==0 )
761
+ {
762
+ m = 0;
763
+ return result;
764
+ }
765
+ internaldstein(n, d, e, m, w, iblock, isplit, z, ifail, cr);
766
+ if( cr!=0 )
767
+ {
768
+ m = 0;
769
+ result = false;
770
+ return result;
771
+ }
772
+
773
+ //
774
+ // Sort eigen values and vectors
775
+ //
776
+ for(i = 1; i <= m; i++)
777
+ {
778
+ k = i;
779
+ for(j = i; j <= m; j++)
780
+ {
781
+ if( w(j)<w(k) )
782
+ {
783
+ k = j;
784
+ }
785
+ }
786
+ v = w(i);
787
+ w(i) = w(k);
788
+ w(k) = v;
789
+ for(j = 1; j <= n; j++)
790
+ {
791
+ v = z(j,i);
792
+ z(j,i) = z(j,k);
793
+ z(j,k) = v;
794
+ }
795
+ }
796
+
797
+ //
798
+ // Store W
799
+ //
800
+ d.setbounds(1, m);
801
+ for(i = 1; i <= m; i++)
802
+ {
803
+ d(i) = w(i);
804
+ }
805
+ return result;
806
+ }
807
+ result = false;
808
+ return result;
809
+ }
810
+
811
+
812
+ /*************************************************************************
813
+ Obsolete 1-based subroutine
814
+ *************************************************************************/
815
+ bool tridiagonaleigenvaluesandvectorsbyindexes(ap::real_1d_array& d,
816
+ const ap::real_1d_array& e,
817
+ int n,
818
+ int zneeded,
819
+ int i1,
820
+ int i2,
821
+ ap::real_2d_array& z)
822
+ {
823
+ bool result;
824
+ int errorcode;
825
+ int nsplit;
826
+ int i;
827
+ int j;
828
+ int k;
829
+ int m;
830
+ int cr;
831
+ ap::integer_1d_array iblock;
832
+ ap::integer_1d_array isplit;
833
+ ap::integer_1d_array ifail;
834
+ ap::real_1d_array w;
835
+ ap::real_2d_array z2;
836
+ ap::real_2d_array z3;
837
+ double v;
838
+
839
+
840
+ //
841
+ // No eigen vectors
842
+ //
843
+ if( zneeded==0 )
844
+ {
845
+ result = internalbisectioneigenvalues(d, e, n, 3, 1, double(0), double(0), i1, i2, double(-1), w, m, nsplit, iblock, isplit, errorcode);
846
+ if( !result )
847
+ {
848
+ return result;
849
+ }
850
+ d.setbounds(1, m);
851
+ for(i = 1; i <= m; i++)
852
+ {
853
+ d(i) = w(i);
854
+ }
855
+ return result;
856
+ }
857
+
858
+ //
859
+ // Eigen vectors are multiplied by Z
860
+ //
861
+ if( zneeded==1 )
862
+ {
863
+
864
+ //
865
+ // Find eigen pairs
866
+ //
867
+ result = internalbisectioneigenvalues(d, e, n, 3, 2, double(0), double(0), i1, i2, double(-1), w, m, nsplit, iblock, isplit, errorcode);
868
+ if( !result )
869
+ {
870
+ return result;
871
+ }
872
+ internaldstein(n, d, e, m, w, iblock, isplit, z2, ifail, cr);
873
+ if( cr!=0 )
874
+ {
875
+ result = false;
876
+ return result;
877
+ }
878
+
879
+ //
880
+ // Sort eigen values and vectors
881
+ //
882
+ for(i = 1; i <= m; i++)
883
+ {
884
+ k = i;
885
+ for(j = i; j <= m; j++)
886
+ {
887
+ if( w(j)<w(k) )
888
+ {
889
+ k = j;
890
+ }
891
+ }
892
+ v = w(i);
893
+ w(i) = w(k);
894
+ w(k) = v;
895
+ for(j = 1; j <= n; j++)
896
+ {
897
+ v = z2(j,i);
898
+ z2(j,i) = z2(j,k);
899
+ z2(j,k) = v;
900
+ }
901
+ }
902
+
903
+ //
904
+ // Transform Z2 and overwrite Z
905
+ //
906
+ z3.setbounds(1, m, 1, n);
907
+ for(i = 1; i <= m; i++)
908
+ {
909
+ ap::vmove(z3.getrow(i, 1, n), z2.getcolumn(i, 1, n));
910
+ }
911
+ for(i = 1; i <= n; i++)
912
+ {
913
+ for(j = 1; j <= m; j++)
914
+ {
915
+ v = ap::vdotproduct(&z(i, 1), &z3(j, 1), ap::vlen(1,n));
916
+ z2(i,j) = v;
917
+ }
918
+ }
919
+ z.setbounds(1, n, 1, m);
920
+ for(i = 1; i <= m; i++)
921
+ {
922
+ ap::vmove(z.getcolumn(i, 1, n), z2.getcolumn(i, 1, n));
923
+ }
924
+
925
+ //
926
+ // Store W
927
+ //
928
+ d.setbounds(1, m);
929
+ for(i = 1; i <= m; i++)
930
+ {
931
+ d(i) = w(i);
932
+ }
933
+ return result;
934
+ }
935
+
936
+ //
937
+ // Eigen vectors are stored in Z
938
+ //
939
+ if( zneeded==2 )
940
+ {
941
+
942
+ //
943
+ // Find eigen pairs
944
+ //
945
+ result = internalbisectioneigenvalues(d, e, n, 3, 2, double(0), double(0), i1, i2, double(-1), w, m, nsplit, iblock, isplit, errorcode);
946
+ if( !result )
947
+ {
948
+ return result;
949
+ }
950
+ internaldstein(n, d, e, m, w, iblock, isplit, z, ifail, cr);
951
+ if( cr!=0 )
952
+ {
953
+ result = false;
954
+ return result;
955
+ }
956
+
957
+ //
958
+ // Sort eigen values and vectors
959
+ //
960
+ for(i = 1; i <= m; i++)
961
+ {
962
+ k = i;
963
+ for(j = i; j <= m; j++)
964
+ {
965
+ if( w(j)<w(k) )
966
+ {
967
+ k = j;
968
+ }
969
+ }
970
+ v = w(i);
971
+ w(i) = w(k);
972
+ w(k) = v;
973
+ for(j = 1; j <= n; j++)
974
+ {
975
+ v = z(j,i);
976
+ z(j,i) = z(j,k);
977
+ z(j,k) = v;
978
+ }
979
+ }
980
+
981
+ //
982
+ // Store W
983
+ //
984
+ d.setbounds(1, m);
985
+ for(i = 1; i <= m; i++)
986
+ {
987
+ d(i) = w(i);
988
+ }
989
+ return result;
990
+ }
991
+ result = false;
992
+ return result;
993
+ }
994
+
995
+
996
+ bool internalbisectioneigenvalues(ap::real_1d_array d,
997
+ ap::real_1d_array e,
998
+ int n,
999
+ int irange,
1000
+ int iorder,
1001
+ double vl,
1002
+ double vu,
1003
+ int il,
1004
+ int iu,
1005
+ double abstol,
1006
+ ap::real_1d_array& w,
1007
+ int& m,
1008
+ int& nsplit,
1009
+ ap::integer_1d_array& iblock,
1010
+ ap::integer_1d_array& isplit,
1011
+ int& errorcode)
1012
+ {
1013
+ bool result;
1014
+ double fudge;
1015
+ double relfac;
1016
+ bool ncnvrg;
1017
+ bool toofew;
1018
+ int ib;
1019
+ int ibegin;
1020
+ int idiscl;
1021
+ int idiscu;
1022
+ int ie;
1023
+ int iend;
1024
+ int iinfo;
1025
+ int im;
1026
+ int iin;
1027
+ int ioff;
1028
+ int iout;
1029
+ int itmax;
1030
+ int iw;
1031
+ int iwoff;
1032
+ int j;
1033
+ int itmp1;
1034
+ int jb;
1035
+ int jdisc;
1036
+ int je;
1037
+ int nwl;
1038
+ int nwu;
1039
+ double atoli;
1040
+ double bnorm;
1041
+ double gl;
1042
+ double gu;
1043
+ double pivmin;
1044
+ double rtoli;
1045
+ double safemn;
1046
+ double tmp1;
1047
+ double tmp2;
1048
+ double tnorm;
1049
+ double ulp;
1050
+ double wkill;
1051
+ double wl;
1052
+ double wlu;
1053
+ double wu;
1054
+ double wul;
1055
+ double scalefactor;
1056
+ double t;
1057
+ ap::integer_1d_array idumma;
1058
+ ap::real_1d_array work;
1059
+ ap::integer_1d_array iwork;
1060
+ ap::integer_1d_array ia1s2;
1061
+ ap::real_1d_array ra1s2;
1062
+ ap::real_2d_array ra1s2x2;
1063
+ ap::integer_2d_array ia1s2x2;
1064
+ ap::real_1d_array ra1siin;
1065
+ ap::real_1d_array ra2siin;
1066
+ ap::real_1d_array ra3siin;
1067
+ ap::real_1d_array ra4siin;
1068
+ ap::real_2d_array ra1siinx2;
1069
+ ap::integer_2d_array ia1siinx2;
1070
+ ap::integer_1d_array iworkspace;
1071
+ ap::real_1d_array rworkspace;
1072
+ int tmpi;
1073
+
1074
+
1075
+ //
1076
+ // Quick return if possible
1077
+ //
1078
+ m = 0;
1079
+ if( n==0 )
1080
+ {
1081
+ result = true;
1082
+ return result;
1083
+ }
1084
+
1085
+ //
1086
+ // Get machine constants
1087
+ // NB is the minimum vector length for vector bisection, or 0
1088
+ // if only scalar is to be done.
1089
+ //
1090
+ fudge = 2;
1091
+ relfac = 2;
1092
+ safemn = ap::minrealnumber;
1093
+ ulp = 2*ap::machineepsilon;
1094
+ rtoli = ulp*relfac;
1095
+ idumma.setbounds(1, 1);
1096
+ work.setbounds(1, 4*n);
1097
+ iwork.setbounds(1, 3*n);
1098
+ w.setbounds(1, n);
1099
+ iblock.setbounds(1, n);
1100
+ isplit.setbounds(1, n);
1101
+ ia1s2.setbounds(1, 2);
1102
+ ra1s2.setbounds(1, 2);
1103
+ ra1s2x2.setbounds(1, 2, 1, 2);
1104
+ ia1s2x2.setbounds(1, 2, 1, 2);
1105
+ ra1siin.setbounds(1, n);
1106
+ ra2siin.setbounds(1, n);
1107
+ ra3siin.setbounds(1, n);
1108
+ ra4siin.setbounds(1, n);
1109
+ ra1siinx2.setbounds(1, n, 1, 2);
1110
+ ia1siinx2.setbounds(1, n, 1, 2);
1111
+ iworkspace.setbounds(1, n);
1112
+ rworkspace.setbounds(1, n);
1113
+
1114
+ //
1115
+ // Check for Errors
1116
+ //
1117
+ result = false;
1118
+ errorcode = 0;
1119
+ if( irange<=0||irange>=4 )
1120
+ {
1121
+ errorcode = -4;
1122
+ }
1123
+ if( iorder<=0||iorder>=3 )
1124
+ {
1125
+ errorcode = -5;
1126
+ }
1127
+ if( n<0 )
1128
+ {
1129
+ errorcode = -3;
1130
+ }
1131
+ if( irange==2&&vl>=vu )
1132
+ {
1133
+ errorcode = -6;
1134
+ }
1135
+ if( irange==3&&(il<1||il>ap::maxint(1, n)) )
1136
+ {
1137
+ errorcode = -8;
1138
+ }
1139
+ if( irange==3&&(iu<ap::minint(n, il)||iu>n) )
1140
+ {
1141
+ errorcode = -9;
1142
+ }
1143
+ if( errorcode!=0 )
1144
+ {
1145
+ return result;
1146
+ }
1147
+
1148
+ //
1149
+ // Initialize error flags
1150
+ //
1151
+ ncnvrg = false;
1152
+ toofew = false;
1153
+
1154
+ //
1155
+ // Simplifications:
1156
+ //
1157
+ if( irange==3&&il==1&&iu==n )
1158
+ {
1159
+ irange = 1;
1160
+ }
1161
+
1162
+ //
1163
+ // Special Case when N=1
1164
+ //
1165
+ if( n==1 )
1166
+ {
1167
+ nsplit = 1;
1168
+ isplit(1) = 1;
1169
+ if( irange==2&&(vl>=d(1)||vu<d(1)) )
1170
+ {
1171
+ m = 0;
1172
+ }
1173
+ else
1174
+ {
1175
+ w(1) = d(1);
1176
+ iblock(1) = 1;
1177
+ m = 1;
1178
+ }
1179
+ result = true;
1180
+ return result;
1181
+ }
1182
+
1183
+ //
1184
+ // Scaling
1185
+ //
1186
+ t = fabs(d(n));
1187
+ for(j = 1; j <= n-1; j++)
1188
+ {
1189
+ t = ap::maxreal(t, fabs(d(j)));
1190
+ t = ap::maxreal(t, fabs(e(j)));
1191
+ }
1192
+ scalefactor = 1;
1193
+ if( t!=0 )
1194
+ {
1195
+ if( t>sqrt(sqrt(ap::minrealnumber))*sqrt(ap::maxrealnumber) )
1196
+ {
1197
+ scalefactor = t;
1198
+ }
1199
+ if( t<sqrt(sqrt(ap::maxrealnumber))*sqrt(ap::minrealnumber) )
1200
+ {
1201
+ scalefactor = t;
1202
+ }
1203
+ for(j = 1; j <= n-1; j++)
1204
+ {
1205
+ d(j) = d(j)/scalefactor;
1206
+ e(j) = e(j)/scalefactor;
1207
+ }
1208
+ d(n) = d(n)/scalefactor;
1209
+ }
1210
+
1211
+ //
1212
+ // Compute Splitting Points
1213
+ //
1214
+ nsplit = 1;
1215
+ work(n) = 0;
1216
+ pivmin = 1;
1217
+ for(j = 2; j <= n; j++)
1218
+ {
1219
+ tmp1 = ap::sqr(e(j-1));
1220
+ if( fabs(d(j)*d(j-1))*ap::sqr(ulp)+safemn>tmp1 )
1221
+ {
1222
+ isplit(nsplit) = j-1;
1223
+ nsplit = nsplit+1;
1224
+ work(j-1) = 0;
1225
+ }
1226
+ else
1227
+ {
1228
+ work(j-1) = tmp1;
1229
+ pivmin = ap::maxreal(pivmin, tmp1);
1230
+ }
1231
+ }
1232
+ isplit(nsplit) = n;
1233
+ pivmin = pivmin*safemn;
1234
+
1235
+ //
1236
+ // Compute Interval and ATOLI
1237
+ //
1238
+ if( irange==3 )
1239
+ {
1240
+
1241
+ //
1242
+ // RANGE='I': Compute the interval containing eigenvalues
1243
+ // IL through IU.
1244
+ //
1245
+ // Compute Gershgorin interval for entire (split) matrix
1246
+ // and use it as the initial interval
1247
+ //
1248
+ gu = d(1);
1249
+ gl = d(1);
1250
+ tmp1 = 0;
1251
+ for(j = 1; j <= n-1; j++)
1252
+ {
1253
+ tmp2 = sqrt(work(j));
1254
+ gu = ap::maxreal(gu, d(j)+tmp1+tmp2);
1255
+ gl = ap::minreal(gl, d(j)-tmp1-tmp2);
1256
+ tmp1 = tmp2;
1257
+ }
1258
+ gu = ap::maxreal(gu, d(n)+tmp1);
1259
+ gl = ap::minreal(gl, d(n)-tmp1);
1260
+ tnorm = ap::maxreal(fabs(gl), fabs(gu));
1261
+ gl = gl-fudge*tnorm*ulp*n-fudge*2*pivmin;
1262
+ gu = gu+fudge*tnorm*ulp*n+fudge*pivmin;
1263
+
1264
+ //
1265
+ // Compute Iteration parameters
1266
+ //
1267
+ itmax = ap::iceil((log(tnorm+pivmin)-log(pivmin))/log(double(2)))+2;
1268
+ if( abstol<=0 )
1269
+ {
1270
+ atoli = ulp*tnorm;
1271
+ }
1272
+ else
1273
+ {
1274
+ atoli = abstol;
1275
+ }
1276
+ work(n+1) = gl;
1277
+ work(n+2) = gl;
1278
+ work(n+3) = gu;
1279
+ work(n+4) = gu;
1280
+ work(n+5) = gl;
1281
+ work(n+6) = gu;
1282
+ iwork(1) = -1;
1283
+ iwork(2) = -1;
1284
+ iwork(3) = n+1;
1285
+ iwork(4) = n+1;
1286
+ iwork(5) = il-1;
1287
+ iwork(6) = iu;
1288
+
1289
+ //
1290
+ // Calling DLAEBZ
1291
+ //
1292
+ // DLAEBZ( 3, ITMAX, N, 2, 2, NB, ATOLI, RTOLI, PIVMIN, D, E,
1293
+ // WORK, IWORK( 5 ), WORK( N+1 ), WORK( N+5 ), IOUT,
1294
+ // IWORK, W, IBLOCK, IINFO )
1295
+ //
1296
+ ia1s2(1) = iwork(5);
1297
+ ia1s2(2) = iwork(6);
1298
+ ra1s2(1) = work(n+5);
1299
+ ra1s2(2) = work(n+6);
1300
+ ra1s2x2(1,1) = work(n+1);
1301
+ ra1s2x2(2,1) = work(n+2);
1302
+ ra1s2x2(1,2) = work(n+3);
1303
+ ra1s2x2(2,2) = work(n+4);
1304
+ ia1s2x2(1,1) = iwork(1);
1305
+ ia1s2x2(2,1) = iwork(2);
1306
+ ia1s2x2(1,2) = iwork(3);
1307
+ ia1s2x2(2,2) = iwork(4);
1308
+ internaldlaebz(3, itmax, n, 2, 2, atoli, rtoli, pivmin, d, e, work, ia1s2, ra1s2x2, ra1s2, iout, ia1s2x2, w, iblock, iinfo);
1309
+ iwork(5) = ia1s2(1);
1310
+ iwork(6) = ia1s2(2);
1311
+ work(n+5) = ra1s2(1);
1312
+ work(n+6) = ra1s2(2);
1313
+ work(n+1) = ra1s2x2(1,1);
1314
+ work(n+2) = ra1s2x2(2,1);
1315
+ work(n+3) = ra1s2x2(1,2);
1316
+ work(n+4) = ra1s2x2(2,2);
1317
+ iwork(1) = ia1s2x2(1,1);
1318
+ iwork(2) = ia1s2x2(2,1);
1319
+ iwork(3) = ia1s2x2(1,2);
1320
+ iwork(4) = ia1s2x2(2,2);
1321
+ if( iwork(6)==iu )
1322
+ {
1323
+ wl = work(n+1);
1324
+ wlu = work(n+3);
1325
+ nwl = iwork(1);
1326
+ wu = work(n+4);
1327
+ wul = work(n+2);
1328
+ nwu = iwork(4);
1329
+ }
1330
+ else
1331
+ {
1332
+ wl = work(n+2);
1333
+ wlu = work(n+4);
1334
+ nwl = iwork(2);
1335
+ wu = work(n+3);
1336
+ wul = work(n+1);
1337
+ nwu = iwork(3);
1338
+ }
1339
+ if( nwl<0||nwl>=n||nwu<1||nwu>n )
1340
+ {
1341
+ errorcode = 4;
1342
+ result = false;
1343
+ return result;
1344
+ }
1345
+ }
1346
+ else
1347
+ {
1348
+
1349
+ //
1350
+ // RANGE='A' or 'V' -- Set ATOLI
1351
+ //
1352
+ tnorm = ap::maxreal(fabs(d(1))+fabs(e(1)), fabs(d(n))+fabs(e(n-1)));
1353
+ for(j = 2; j <= n-1; j++)
1354
+ {
1355
+ tnorm = ap::maxreal(tnorm, fabs(d(j))+fabs(e(j-1))+fabs(e(j)));
1356
+ }
1357
+ if( abstol<=0 )
1358
+ {
1359
+ atoli = ulp*tnorm;
1360
+ }
1361
+ else
1362
+ {
1363
+ atoli = abstol;
1364
+ }
1365
+ if( irange==2 )
1366
+ {
1367
+ wl = vl;
1368
+ wu = vu;
1369
+ }
1370
+ else
1371
+ {
1372
+ wl = 0;
1373
+ wu = 0;
1374
+ }
1375
+ }
1376
+
1377
+ //
1378
+ // Find Eigenvalues -- Loop Over Blocks and recompute NWL and NWU.
1379
+ // NWL accumulates the number of eigenvalues .le. WL,
1380
+ // NWU accumulates the number of eigenvalues .le. WU
1381
+ //
1382
+ m = 0;
1383
+ iend = 0;
1384
+ errorcode = 0;
1385
+ nwl = 0;
1386
+ nwu = 0;
1387
+ for(jb = 1; jb <= nsplit; jb++)
1388
+ {
1389
+ ioff = iend;
1390
+ ibegin = ioff+1;
1391
+ iend = isplit(jb);
1392
+ iin = iend-ioff;
1393
+ if( iin==1 )
1394
+ {
1395
+
1396
+ //
1397
+ // Special Case -- IIN=1
1398
+ //
1399
+ if( irange==1||wl>=d(ibegin)-pivmin )
1400
+ {
1401
+ nwl = nwl+1;
1402
+ }
1403
+ if( irange==1||wu>=d(ibegin)-pivmin )
1404
+ {
1405
+ nwu = nwu+1;
1406
+ }
1407
+ if( irange==1||wl<d(ibegin)-pivmin&&wu>=d(ibegin)-pivmin )
1408
+ {
1409
+ m = m+1;
1410
+ w(m) = d(ibegin);
1411
+ iblock(m) = jb;
1412
+ }
1413
+ }
1414
+ else
1415
+ {
1416
+
1417
+ //
1418
+ // General Case -- IIN > 1
1419
+ //
1420
+ // Compute Gershgorin Interval
1421
+ // and use it as the initial interval
1422
+ //
1423
+ gu = d(ibegin);
1424
+ gl = d(ibegin);
1425
+ tmp1 = 0;
1426
+ for(j = ibegin; j <= iend-1; j++)
1427
+ {
1428
+ tmp2 = fabs(e(j));
1429
+ gu = ap::maxreal(gu, d(j)+tmp1+tmp2);
1430
+ gl = ap::minreal(gl, d(j)-tmp1-tmp2);
1431
+ tmp1 = tmp2;
1432
+ }
1433
+ gu = ap::maxreal(gu, d(iend)+tmp1);
1434
+ gl = ap::minreal(gl, d(iend)-tmp1);
1435
+ bnorm = ap::maxreal(fabs(gl), fabs(gu));
1436
+ gl = gl-fudge*bnorm*ulp*iin-fudge*pivmin;
1437
+ gu = gu+fudge*bnorm*ulp*iin+fudge*pivmin;
1438
+
1439
+ //
1440
+ // Compute ATOLI for the current submatrix
1441
+ //
1442
+ if( abstol<=0 )
1443
+ {
1444
+ atoli = ulp*ap::maxreal(fabs(gl), fabs(gu));
1445
+ }
1446
+ else
1447
+ {
1448
+ atoli = abstol;
1449
+ }
1450
+ if( irange>1 )
1451
+ {
1452
+ if( gu<wl )
1453
+ {
1454
+ nwl = nwl+iin;
1455
+ nwu = nwu+iin;
1456
+ continue;
1457
+ }
1458
+ gl = ap::maxreal(gl, wl);
1459
+ gu = ap::minreal(gu, wu);
1460
+ if( gl>=gu )
1461
+ {
1462
+ continue;
1463
+ }
1464
+ }
1465
+
1466
+ //
1467
+ // Set Up Initial Interval
1468
+ //
1469
+ work(n+1) = gl;
1470
+ work(n+iin+1) = gu;
1471
+
1472
+ //
1473
+ // Calling DLAEBZ
1474
+ //
1475
+ // CALL DLAEBZ( 1, 0, IN, IN, 1, NB, ATOLI, RTOLI, PIVMIN,
1476
+ // D( IBEGIN ), E( IBEGIN ), WORK( IBEGIN ),
1477
+ // IDUMMA, WORK( N+1 ), WORK( N+2*IN+1 ), IM,
1478
+ // IWORK, W( M+1 ), IBLOCK( M+1 ), IINFO )
1479
+ //
1480
+ for(tmpi = 1; tmpi <= iin; tmpi++)
1481
+ {
1482
+ ra1siin(tmpi) = d(ibegin-1+tmpi);
1483
+ if( ibegin-1+tmpi<n )
1484
+ {
1485
+ ra2siin(tmpi) = e(ibegin-1+tmpi);
1486
+ }
1487
+ ra3siin(tmpi) = work(ibegin-1+tmpi);
1488
+ ra1siinx2(tmpi,1) = work(n+tmpi);
1489
+ ra1siinx2(tmpi,2) = work(n+tmpi+iin);
1490
+ ra4siin(tmpi) = work(n+2*iin+tmpi);
1491
+ rworkspace(tmpi) = w(m+tmpi);
1492
+ iworkspace(tmpi) = iblock(m+tmpi);
1493
+ ia1siinx2(tmpi,1) = iwork(tmpi);
1494
+ ia1siinx2(tmpi,2) = iwork(tmpi+iin);
1495
+ }
1496
+ internaldlaebz(1, 0, iin, iin, 1, atoli, rtoli, pivmin, ra1siin, ra2siin, ra3siin, idumma, ra1siinx2, ra4siin, im, ia1siinx2, rworkspace, iworkspace, iinfo);
1497
+ for(tmpi = 1; tmpi <= iin; tmpi++)
1498
+ {
1499
+ work(n+tmpi) = ra1siinx2(tmpi,1);
1500
+ work(n+tmpi+iin) = ra1siinx2(tmpi,2);
1501
+ work(n+2*iin+tmpi) = ra4siin(tmpi);
1502
+ w(m+tmpi) = rworkspace(tmpi);
1503
+ iblock(m+tmpi) = iworkspace(tmpi);
1504
+ iwork(tmpi) = ia1siinx2(tmpi,1);
1505
+ iwork(tmpi+iin) = ia1siinx2(tmpi,2);
1506
+ }
1507
+ nwl = nwl+iwork(1);
1508
+ nwu = nwu+iwork(iin+1);
1509
+ iwoff = m-iwork(1);
1510
+
1511
+ //
1512
+ // Compute Eigenvalues
1513
+ //
1514
+ itmax = ap::iceil((log(gu-gl+pivmin)-log(pivmin))/log(double(2)))+2;
1515
+
1516
+ //
1517
+ // Calling DLAEBZ
1518
+ //
1519
+ //CALL DLAEBZ( 2, ITMAX, IN, IN, 1, NB, ATOLI, RTOLI, PIVMIN,
1520
+ // D( IBEGIN ), E( IBEGIN ), WORK( IBEGIN ),
1521
+ // IDUMMA, WORK( N+1 ), WORK( N+2*IN+1 ), IOUT,
1522
+ // IWORK, W( M+1 ), IBLOCK( M+1 ), IINFO )
1523
+ //
1524
+ for(tmpi = 1; tmpi <= iin; tmpi++)
1525
+ {
1526
+ ra1siin(tmpi) = d(ibegin-1+tmpi);
1527
+ if( ibegin-1+tmpi<n )
1528
+ {
1529
+ ra2siin(tmpi) = e(ibegin-1+tmpi);
1530
+ }
1531
+ ra3siin(tmpi) = work(ibegin-1+tmpi);
1532
+ ra1siinx2(tmpi,1) = work(n+tmpi);
1533
+ ra1siinx2(tmpi,2) = work(n+tmpi+iin);
1534
+ ra4siin(tmpi) = work(n+2*iin+tmpi);
1535
+ rworkspace(tmpi) = w(m+tmpi);
1536
+ iworkspace(tmpi) = iblock(m+tmpi);
1537
+ ia1siinx2(tmpi,1) = iwork(tmpi);
1538
+ ia1siinx2(tmpi,2) = iwork(tmpi+iin);
1539
+ }
1540
+ internaldlaebz(2, itmax, iin, iin, 1, atoli, rtoli, pivmin, ra1siin, ra2siin, ra3siin, idumma, ra1siinx2, ra4siin, iout, ia1siinx2, rworkspace, iworkspace, iinfo);
1541
+ for(tmpi = 1; tmpi <= iin; tmpi++)
1542
+ {
1543
+ work(n+tmpi) = ra1siinx2(tmpi,1);
1544
+ work(n+tmpi+iin) = ra1siinx2(tmpi,2);
1545
+ work(n+2*iin+tmpi) = ra4siin(tmpi);
1546
+ w(m+tmpi) = rworkspace(tmpi);
1547
+ iblock(m+tmpi) = iworkspace(tmpi);
1548
+ iwork(tmpi) = ia1siinx2(tmpi,1);
1549
+ iwork(tmpi+iin) = ia1siinx2(tmpi,2);
1550
+ }
1551
+
1552
+ //
1553
+ // Copy Eigenvalues Into W and IBLOCK
1554
+ // Use -JB for block number for unconverged eigenvalues.
1555
+ //
1556
+ for(j = 1; j <= iout; j++)
1557
+ {
1558
+ tmp1 = 0.5*(work(j+n)+work(j+iin+n));
1559
+
1560
+ //
1561
+ // Flag non-convergence.
1562
+ //
1563
+ if( j>iout-iinfo )
1564
+ {
1565
+ ncnvrg = true;
1566
+ ib = -jb;
1567
+ }
1568
+ else
1569
+ {
1570
+ ib = jb;
1571
+ }
1572
+ for(je = iwork(j)+1+iwoff; je <= iwork(j+iin)+iwoff; je++)
1573
+ {
1574
+ w(je) = tmp1;
1575
+ iblock(je) = ib;
1576
+ }
1577
+ }
1578
+ m = m+im;
1579
+ }
1580
+ }
1581
+
1582
+ //
1583
+ // If RANGE='I', then (WL,WU) contains eigenvalues NWL+1,...,NWU
1584
+ // If NWL+1 < IL or NWU > IU, discard extra eigenvalues.
1585
+ //
1586
+ if( irange==3 )
1587
+ {
1588
+ im = 0;
1589
+ idiscl = il-1-nwl;
1590
+ idiscu = nwu-iu;
1591
+ if( idiscl>0||idiscu>0 )
1592
+ {
1593
+ for(je = 1; je <= m; je++)
1594
+ {
1595
+ if( w(je)<=wlu&&idiscl>0 )
1596
+ {
1597
+ idiscl = idiscl-1;
1598
+ }
1599
+ else
1600
+ {
1601
+ if( w(je)>=wul&&idiscu>0 )
1602
+ {
1603
+ idiscu = idiscu-1;
1604
+ }
1605
+ else
1606
+ {
1607
+ im = im+1;
1608
+ w(im) = w(je);
1609
+ iblock(im) = iblock(je);
1610
+ }
1611
+ }
1612
+ }
1613
+ m = im;
1614
+ }
1615
+ if( idiscl>0||idiscu>0 )
1616
+ {
1617
+
1618
+ //
1619
+ // Code to deal with effects of bad arithmetic:
1620
+ // Some low eigenvalues to be discarded are not in (WL,WLU],
1621
+ // or high eigenvalues to be discarded are not in (WUL,WU]
1622
+ // so just kill off the smallest IDISCL/largest IDISCU
1623
+ // eigenvalues, by simply finding the smallest/largest
1624
+ // eigenvalue(s).
1625
+ //
1626
+ // (If N(w) is monotone non-decreasing, this should never
1627
+ // happen.)
1628
+ //
1629
+ if( idiscl>0 )
1630
+ {
1631
+ wkill = wu;
1632
+ for(jdisc = 1; jdisc <= idiscl; jdisc++)
1633
+ {
1634
+ iw = 0;
1635
+ for(je = 1; je <= m; je++)
1636
+ {
1637
+ if( iblock(je)!=0&&(w(je)<wkill||iw==0) )
1638
+ {
1639
+ iw = je;
1640
+ wkill = w(je);
1641
+ }
1642
+ }
1643
+ iblock(iw) = 0;
1644
+ }
1645
+ }
1646
+ if( idiscu>0 )
1647
+ {
1648
+ wkill = wl;
1649
+ for(jdisc = 1; jdisc <= idiscu; jdisc++)
1650
+ {
1651
+ iw = 0;
1652
+ for(je = 1; je <= m; je++)
1653
+ {
1654
+ if( iblock(je)!=0&&(w(je)>wkill||iw==0) )
1655
+ {
1656
+ iw = je;
1657
+ wkill = w(je);
1658
+ }
1659
+ }
1660
+ iblock(iw) = 0;
1661
+ }
1662
+ }
1663
+ im = 0;
1664
+ for(je = 1; je <= m; je++)
1665
+ {
1666
+ if( iblock(je)!=0 )
1667
+ {
1668
+ im = im+1;
1669
+ w(im) = w(je);
1670
+ iblock(im) = iblock(je);
1671
+ }
1672
+ }
1673
+ m = im;
1674
+ }
1675
+ if( idiscl<0||idiscu<0 )
1676
+ {
1677
+ toofew = true;
1678
+ }
1679
+ }
1680
+
1681
+ //
1682
+ // If ORDER='B', do nothing -- the eigenvalues are already sorted
1683
+ // by block.
1684
+ // If ORDER='E', sort the eigenvalues from smallest to largest
1685
+ //
1686
+ if( iorder==1&&nsplit>1 )
1687
+ {
1688
+ for(je = 1; je <= m-1; je++)
1689
+ {
1690
+ ie = 0;
1691
+ tmp1 = w(je);
1692
+ for(j = je+1; j <= m; j++)
1693
+ {
1694
+ if( w(j)<tmp1 )
1695
+ {
1696
+ ie = j;
1697
+ tmp1 = w(j);
1698
+ }
1699
+ }
1700
+ if( ie!=0 )
1701
+ {
1702
+ itmp1 = iblock(ie);
1703
+ w(ie) = w(je);
1704
+ iblock(ie) = iblock(je);
1705
+ w(je) = tmp1;
1706
+ iblock(je) = itmp1;
1707
+ }
1708
+ }
1709
+ }
1710
+ for(j = 1; j <= m; j++)
1711
+ {
1712
+ w(j) = w(j)*scalefactor;
1713
+ }
1714
+ errorcode = 0;
1715
+ if( ncnvrg )
1716
+ {
1717
+ errorcode = errorcode+1;
1718
+ }
1719
+ if( toofew )
1720
+ {
1721
+ errorcode = errorcode+2;
1722
+ }
1723
+ result = errorcode==0;
1724
+ return result;
1725
+ }
1726
+
1727
+
1728
+ void internaldstein(const int& n,
1729
+ const ap::real_1d_array& d,
1730
+ ap::real_1d_array e,
1731
+ const int& m,
1732
+ ap::real_1d_array w,
1733
+ const ap::integer_1d_array& iblock,
1734
+ const ap::integer_1d_array& isplit,
1735
+ ap::real_2d_array& z,
1736
+ ap::integer_1d_array& ifail,
1737
+ int& info)
1738
+ {
1739
+ int maxits;
1740
+ int extra;
1741
+ int b1;
1742
+ int blksiz;
1743
+ int bn;
1744
+ int gpind;
1745
+ int i;
1746
+ int iinfo;
1747
+ int its;
1748
+ int j;
1749
+ int j1;
1750
+ int jblk;
1751
+ int jmax;
1752
+ int nblk;
1753
+ int nrmchk;
1754
+ double dtpcrt;
1755
+ double eps;
1756
+ double eps1;
1757
+ double nrm;
1758
+ double onenrm;
1759
+ double ortol;
1760
+ double pertol;
1761
+ double scl;
1762
+ double sep;
1763
+ double tol;
1764
+ double xj;
1765
+ double xjm;
1766
+ double ztr;
1767
+ ap::real_1d_array work1;
1768
+ ap::real_1d_array work2;
1769
+ ap::real_1d_array work3;
1770
+ ap::real_1d_array work4;
1771
+ ap::real_1d_array work5;
1772
+ ap::integer_1d_array iwork;
1773
+ bool tmpcriterion;
1774
+ int ti;
1775
+ int i1;
1776
+ int i2;
1777
+ double v;
1778
+
1779
+ maxits = 5;
1780
+ extra = 2;
1781
+ work1.setbounds(1, ap::maxint(n, 1));
1782
+ work2.setbounds(1, ap::maxint(n-1, 1));
1783
+ work3.setbounds(1, ap::maxint(n, 1));
1784
+ work4.setbounds(1, ap::maxint(n, 1));
1785
+ work5.setbounds(1, ap::maxint(n, 1));
1786
+ iwork.setbounds(1, ap::maxint(n, 1));
1787
+ ifail.setbounds(1, ap::maxint(m, 1));
1788
+ z.setbounds(1, ap::maxint(n, 1), 1, ap::maxint(m, 1));
1789
+
1790
+ //
1791
+ // Test the input parameters.
1792
+ //
1793
+ info = 0;
1794
+ for(i = 1; i <= m; i++)
1795
+ {
1796
+ ifail(i) = 0;
1797
+ }
1798
+ if( n<0 )
1799
+ {
1800
+ info = -1;
1801
+ return;
1802
+ }
1803
+ if( m<0||m>n )
1804
+ {
1805
+ info = -4;
1806
+ return;
1807
+ }
1808
+ for(j = 2; j <= m; j++)
1809
+ {
1810
+ if( iblock(j)<iblock(j-1) )
1811
+ {
1812
+ info = -6;
1813
+ break;
1814
+ }
1815
+ if( iblock(j)==iblock(j-1)&&w(j)<w(j-1) )
1816
+ {
1817
+ info = -5;
1818
+ break;
1819
+ }
1820
+ }
1821
+ if( info!=0 )
1822
+ {
1823
+ return;
1824
+ }
1825
+
1826
+ //
1827
+ // Quick return if possible
1828
+ //
1829
+ if( n==0||m==0 )
1830
+ {
1831
+ return;
1832
+ }
1833
+ if( n==1 )
1834
+ {
1835
+ z(1,1) = 1;
1836
+ return;
1837
+ }
1838
+
1839
+ //
1840
+ // Some preparations
1841
+ //
1842
+ ti = n-1;
1843
+ ap::vmove(&work1(1), &e(1), ap::vlen(1,ti));
1844
+ e.setbounds(1, n);
1845
+ ap::vmove(&e(1), &work1(1), ap::vlen(1,ti));
1846
+ ap::vmove(&work1(1), &w(1), ap::vlen(1,m));
1847
+ w.setbounds(1, n);
1848
+ ap::vmove(&w(1), &work1(1), ap::vlen(1,m));
1849
+
1850
+ //
1851
+ // Get machine constants.
1852
+ //
1853
+ eps = ap::machineepsilon;
1854
+
1855
+ //
1856
+ // Compute eigenvectors of matrix blocks.
1857
+ //
1858
+ j1 = 1;
1859
+ for(nblk = 1; nblk <= iblock(m); nblk++)
1860
+ {
1861
+
1862
+ //
1863
+ // Find starting and ending indices of block nblk.
1864
+ //
1865
+ if( nblk==1 )
1866
+ {
1867
+ b1 = 1;
1868
+ }
1869
+ else
1870
+ {
1871
+ b1 = isplit(nblk-1)+1;
1872
+ }
1873
+ bn = isplit(nblk);
1874
+ blksiz = bn-b1+1;
1875
+ if( blksiz!=1 )
1876
+ {
1877
+
1878
+ //
1879
+ // Compute reorthogonalization criterion and stopping criterion.
1880
+ //
1881
+ gpind = b1;
1882
+ onenrm = fabs(d(b1))+fabs(e(b1));
1883
+ onenrm = ap::maxreal(onenrm, fabs(d(bn))+fabs(e(bn-1)));
1884
+ for(i = b1+1; i <= bn-1; i++)
1885
+ {
1886
+ onenrm = ap::maxreal(onenrm, fabs(d(i))+fabs(e(i-1))+fabs(e(i)));
1887
+ }
1888
+ ortol = 0.001*onenrm;
1889
+ dtpcrt = sqrt(0.1/blksiz);
1890
+ }
1891
+
1892
+ //
1893
+ // Loop through eigenvalues of block nblk.
1894
+ //
1895
+ jblk = 0;
1896
+ for(j = j1; j <= m; j++)
1897
+ {
1898
+ if( iblock(j)!=nblk )
1899
+ {
1900
+ j1 = j;
1901
+ break;
1902
+ }
1903
+ jblk = jblk+1;
1904
+ xj = w(j);
1905
+ if( blksiz==1 )
1906
+ {
1907
+
1908
+ //
1909
+ // Skip all the work if the block size is one.
1910
+ //
1911
+ work1(1) = 1;
1912
+ }
1913
+ else
1914
+ {
1915
+
1916
+ //
1917
+ // If eigenvalues j and j-1 are too close, add a relatively
1918
+ // small perturbation.
1919
+ //
1920
+ if( jblk>1 )
1921
+ {
1922
+ eps1 = fabs(eps*xj);
1923
+ pertol = 10*eps1;
1924
+ sep = xj-xjm;
1925
+ if( sep<pertol )
1926
+ {
1927
+ xj = xjm+pertol;
1928
+ }
1929
+ }
1930
+ its = 0;
1931
+ nrmchk = 0;
1932
+
1933
+ //
1934
+ // Get random starting vector.
1935
+ //
1936
+ for(ti = 1; ti <= blksiz; ti++)
1937
+ {
1938
+ work1(ti) = 2*ap::randomreal()-1;
1939
+ }
1940
+
1941
+ //
1942
+ // Copy the matrix T so it won't be destroyed in factorization.
1943
+ //
1944
+ for(ti = 1; ti <= blksiz-1; ti++)
1945
+ {
1946
+ work2(ti) = e(b1+ti-1);
1947
+ work3(ti) = e(b1+ti-1);
1948
+ work4(ti) = d(b1+ti-1);
1949
+ }
1950
+ work4(blksiz) = d(b1+blksiz-1);
1951
+
1952
+ //
1953
+ // Compute LU factors with partial pivoting ( PT = LU )
1954
+ //
1955
+ tol = 0;
1956
+ tdininternaldlagtf(blksiz, work4, xj, work2, work3, tol, work5, iwork, iinfo);
1957
+
1958
+ //
1959
+ // Update iteration count.
1960
+ //
1961
+ do
1962
+ {
1963
+ its = its+1;
1964
+ if( its>maxits )
1965
+ {
1966
+
1967
+ //
1968
+ // If stopping criterion was not satisfied, update info and
1969
+ // store eigenvector number in array ifail.
1970
+ //
1971
+ info = info+1;
1972
+ ifail(info) = j;
1973
+ break;
1974
+ }
1975
+
1976
+ //
1977
+ // Normalize and scale the righthand side vector Pb.
1978
+ //
1979
+ v = 0;
1980
+ for(ti = 1; ti <= blksiz; ti++)
1981
+ {
1982
+ v = v+fabs(work1(ti));
1983
+ }
1984
+ scl = blksiz*onenrm*ap::maxreal(eps, fabs(work4(blksiz)))/v;
1985
+ ap::vmul(&work1(1), ap::vlen(1,blksiz), scl);
1986
+
1987
+ //
1988
+ // Solve the system LU = Pb.
1989
+ //
1990
+ tdininternaldlagts(blksiz, work4, work2, work3, work5, iwork, work1, tol, iinfo);
1991
+
1992
+ //
1993
+ // Reorthogonalize by modified Gram-Schmidt if eigenvalues are
1994
+ // close enough.
1995
+ //
1996
+ if( jblk!=1 )
1997
+ {
1998
+ if( fabs(xj-xjm)>ortol )
1999
+ {
2000
+ gpind = j;
2001
+ }
2002
+ if( gpind!=j )
2003
+ {
2004
+ for(i = gpind; i <= j-1; i++)
2005
+ {
2006
+ i1 = b1;
2007
+ i2 = b1+blksiz-1;
2008
+ ztr = ap::vdotproduct(work1.getvector(1, blksiz), z.getcolumn(i, i1, i2));
2009
+ ap::vsub(work1.getvector(1, blksiz), z.getcolumn(i, i1, i2), ztr);
2010
+ }
2011
+ }
2012
+ }
2013
+
2014
+ //
2015
+ // Check the infinity norm of the iterate.
2016
+ //
2017
+ jmax = vectoridxabsmax(work1, 1, blksiz);
2018
+ nrm = fabs(work1(jmax));
2019
+
2020
+ //
2021
+ // Continue for additional iterations after norm reaches
2022
+ // stopping criterion.
2023
+ //
2024
+ tmpcriterion = false;
2025
+ if( nrm<dtpcrt )
2026
+ {
2027
+ tmpcriterion = true;
2028
+ }
2029
+ else
2030
+ {
2031
+ nrmchk = nrmchk+1;
2032
+ if( nrmchk<extra+1 )
2033
+ {
2034
+ tmpcriterion = true;
2035
+ }
2036
+ }
2037
+ }
2038
+ while(tmpcriterion);
2039
+
2040
+ //
2041
+ // Accept iterate as jth eigenvector.
2042
+ //
2043
+ scl = 1/vectornorm2(work1, 1, blksiz);
2044
+ jmax = vectoridxabsmax(work1, 1, blksiz);
2045
+ if( work1(jmax)<0 )
2046
+ {
2047
+ scl = -scl;
2048
+ }
2049
+ ap::vmul(&work1(1), ap::vlen(1,blksiz), scl);
2050
+ }
2051
+ for(i = 1; i <= n; i++)
2052
+ {
2053
+ z(i,j) = 0;
2054
+ }
2055
+ for(i = 1; i <= blksiz; i++)
2056
+ {
2057
+ z(b1+i-1,j) = work1(i);
2058
+ }
2059
+
2060
+ //
2061
+ // Save the shift to check eigenvalue spacing at next
2062
+ // iteration.
2063
+ //
2064
+ xjm = xj;
2065
+ }
2066
+ }
2067
+ }
2068
+
2069
+
2070
+ static void tdininternaldlagtf(const int& n,
2071
+ ap::real_1d_array& a,
2072
+ const double& lambda,
2073
+ ap::real_1d_array& b,
2074
+ ap::real_1d_array& c,
2075
+ const double& tol,
2076
+ ap::real_1d_array& d,
2077
+ ap::integer_1d_array& iin,
2078
+ int& info)
2079
+ {
2080
+ int k;
2081
+ double eps;
2082
+ double mult;
2083
+ double piv1;
2084
+ double piv2;
2085
+ double scale1;
2086
+ double scale2;
2087
+ double temp;
2088
+ double tl;
2089
+
2090
+ info = 0;
2091
+ if( n<0 )
2092
+ {
2093
+ info = -1;
2094
+ return;
2095
+ }
2096
+ if( n==0 )
2097
+ {
2098
+ return;
2099
+ }
2100
+ a(1) = a(1)-lambda;
2101
+ iin(n) = 0;
2102
+ if( n==1 )
2103
+ {
2104
+ if( a(1)==0 )
2105
+ {
2106
+ iin(1) = 1;
2107
+ }
2108
+ return;
2109
+ }
2110
+ eps = ap::machineepsilon;
2111
+ tl = ap::maxreal(tol, eps);
2112
+ scale1 = fabs(a(1))+fabs(b(1));
2113
+ for(k = 1; k <= n-1; k++)
2114
+ {
2115
+ a(k+1) = a(k+1)-lambda;
2116
+ scale2 = fabs(c(k))+fabs(a(k+1));
2117
+ if( k<n-1 )
2118
+ {
2119
+ scale2 = scale2+fabs(b(k+1));
2120
+ }
2121
+ if( a(k)==0 )
2122
+ {
2123
+ piv1 = 0;
2124
+ }
2125
+ else
2126
+ {
2127
+ piv1 = fabs(a(k))/scale1;
2128
+ }
2129
+ if( c(k)==0 )
2130
+ {
2131
+ iin(k) = 0;
2132
+ piv2 = 0;
2133
+ scale1 = scale2;
2134
+ if( k<n-1 )
2135
+ {
2136
+ d(k) = 0;
2137
+ }
2138
+ }
2139
+ else
2140
+ {
2141
+ piv2 = fabs(c(k))/scale2;
2142
+ if( piv2<=piv1 )
2143
+ {
2144
+ iin(k) = 0;
2145
+ scale1 = scale2;
2146
+ c(k) = c(k)/a(k);
2147
+ a(k+1) = a(k+1)-c(k)*b(k);
2148
+ if( k<n-1 )
2149
+ {
2150
+ d(k) = 0;
2151
+ }
2152
+ }
2153
+ else
2154
+ {
2155
+ iin(k) = 1;
2156
+ mult = a(k)/c(k);
2157
+ a(k) = c(k);
2158
+ temp = a(k+1);
2159
+ a(k+1) = b(k)-mult*temp;
2160
+ if( k<n-1 )
2161
+ {
2162
+ d(k) = b(k+1);
2163
+ b(k+1) = -mult*d(k);
2164
+ }
2165
+ b(k) = temp;
2166
+ c(k) = mult;
2167
+ }
2168
+ }
2169
+ if( ap::maxreal(piv1, piv2)<=tl&&iin(n)==0 )
2170
+ {
2171
+ iin(n) = k;
2172
+ }
2173
+ }
2174
+ if( fabs(a(n))<=scale1*tl&&iin(n)==0 )
2175
+ {
2176
+ iin(n) = n;
2177
+ }
2178
+ }
2179
+
2180
+
2181
+ static void tdininternaldlagts(const int& n,
2182
+ const ap::real_1d_array& a,
2183
+ const ap::real_1d_array& b,
2184
+ const ap::real_1d_array& c,
2185
+ const ap::real_1d_array& d,
2186
+ const ap::integer_1d_array& iin,
2187
+ ap::real_1d_array& y,
2188
+ double& tol,
2189
+ int& info)
2190
+ {
2191
+ int k;
2192
+ double absak;
2193
+ double ak;
2194
+ double bignum;
2195
+ double eps;
2196
+ double pert;
2197
+ double sfmin;
2198
+ double temp;
2199
+
2200
+ info = 0;
2201
+ if( n<0 )
2202
+ {
2203
+ info = -1;
2204
+ return;
2205
+ }
2206
+ if( n==0 )
2207
+ {
2208
+ return;
2209
+ }
2210
+ eps = ap::machineepsilon;
2211
+ sfmin = ap::minrealnumber;
2212
+ bignum = 1/sfmin;
2213
+ if( tol<=0 )
2214
+ {
2215
+ tol = fabs(a(1));
2216
+ if( n>1 )
2217
+ {
2218
+ tol = ap::maxreal(tol, ap::maxreal(fabs(a(2)), fabs(b(1))));
2219
+ }
2220
+ for(k = 3; k <= n; k++)
2221
+ {
2222
+ tol = ap::maxreal(tol, ap::maxreal(fabs(a(k)), ap::maxreal(fabs(b(k-1)), fabs(d(k-2)))));
2223
+ }
2224
+ tol = tol*eps;
2225
+ if( tol==0 )
2226
+ {
2227
+ tol = eps;
2228
+ }
2229
+ }
2230
+ for(k = 2; k <= n; k++)
2231
+ {
2232
+ if( iin(k-1)==0 )
2233
+ {
2234
+ y(k) = y(k)-c(k-1)*y(k-1);
2235
+ }
2236
+ else
2237
+ {
2238
+ temp = y(k-1);
2239
+ y(k-1) = y(k);
2240
+ y(k) = temp-c(k-1)*y(k);
2241
+ }
2242
+ }
2243
+ for(k = n; k >= 1; k--)
2244
+ {
2245
+ if( k<=n-2 )
2246
+ {
2247
+ temp = y(k)-b(k)*y(k+1)-d(k)*y(k+2);
2248
+ }
2249
+ else
2250
+ {
2251
+ if( k==n-1 )
2252
+ {
2253
+ temp = y(k)-b(k)*y(k+1);
2254
+ }
2255
+ else
2256
+ {
2257
+ temp = y(k);
2258
+ }
2259
+ }
2260
+ ak = a(k);
2261
+ pert = fabs(tol);
2262
+ if( ak<0 )
2263
+ {
2264
+ pert = -pert;
2265
+ }
2266
+ while(true)
2267
+ {
2268
+ absak = fabs(ak);
2269
+ if( absak<1 )
2270
+ {
2271
+ if( absak<sfmin )
2272
+ {
2273
+ if( absak==0||fabs(temp)*sfmin>absak )
2274
+ {
2275
+ ak = ak+pert;
2276
+ pert = 2*pert;
2277
+ continue;
2278
+ }
2279
+ else
2280
+ {
2281
+ temp = temp*bignum;
2282
+ ak = ak*bignum;
2283
+ }
2284
+ }
2285
+ else
2286
+ {
2287
+ if( fabs(temp)>absak*bignum )
2288
+ {
2289
+ ak = ak+pert;
2290
+ pert = 2*pert;
2291
+ continue;
2292
+ }
2293
+ }
2294
+ }
2295
+ break;
2296
+ }
2297
+ y(k) = temp/ak;
2298
+ }
2299
+ }
2300
+
2301
+
2302
+ static void internaldlaebz(const int& ijob,
2303
+ const int& nitmax,
2304
+ const int& n,
2305
+ const int& mmax,
2306
+ const int& minp,
2307
+ const double& abstol,
2308
+ const double& reltol,
2309
+ const double& pivmin,
2310
+ const ap::real_1d_array& d,
2311
+ const ap::real_1d_array& e,
2312
+ const ap::real_1d_array& e2,
2313
+ ap::integer_1d_array& nval,
2314
+ ap::real_2d_array& ab,
2315
+ ap::real_1d_array& c,
2316
+ int& mout,
2317
+ ap::integer_2d_array& nab,
2318
+ ap::real_1d_array& work,
2319
+ ap::integer_1d_array& iwork,
2320
+ int& info)
2321
+ {
2322
+ int itmp1;
2323
+ int itmp2;
2324
+ int j;
2325
+ int ji;
2326
+ int jit;
2327
+ int jp;
2328
+ int kf;
2329
+ int kfnew;
2330
+ int kl;
2331
+ int klnew;
2332
+ double tmp1;
2333
+ double tmp2;
2334
+
2335
+ info = 0;
2336
+ if( ijob<1||ijob>3 )
2337
+ {
2338
+ info = -1;
2339
+ return;
2340
+ }
2341
+
2342
+ //
2343
+ // Initialize NAB
2344
+ //
2345
+ if( ijob==1 )
2346
+ {
2347
+
2348
+ //
2349
+ // Compute the number of eigenvalues in the initial intervals.
2350
+ //
2351
+ mout = 0;
2352
+
2353
+ //
2354
+ //DIR$ NOVECTOR
2355
+ //
2356
+ for(ji = 1; ji <= minp; ji++)
2357
+ {
2358
+ for(jp = 1; jp <= 2; jp++)
2359
+ {
2360
+ tmp1 = d(1)-ab(ji,jp);
2361
+ if( fabs(tmp1)<pivmin )
2362
+ {
2363
+ tmp1 = -pivmin;
2364
+ }
2365
+ nab(ji,jp) = 0;
2366
+ if( tmp1<=0 )
2367
+ {
2368
+ nab(ji,jp) = 1;
2369
+ }
2370
+ for(j = 2; j <= n; j++)
2371
+ {
2372
+ tmp1 = d(j)-e2(j-1)/tmp1-ab(ji,jp);
2373
+ if( fabs(tmp1)<pivmin )
2374
+ {
2375
+ tmp1 = -pivmin;
2376
+ }
2377
+ if( tmp1<=0 )
2378
+ {
2379
+ nab(ji,jp) = nab(ji,jp)+1;
2380
+ }
2381
+ }
2382
+ }
2383
+ mout = mout+nab(ji,2)-nab(ji,1);
2384
+ }
2385
+ return;
2386
+ }
2387
+
2388
+ //
2389
+ // Initialize for loop
2390
+ //
2391
+ // KF and KL have the following meaning:
2392
+ // Intervals 1,...,KF-1 have converged.
2393
+ // Intervals KF,...,KL still need to be refined.
2394
+ //
2395
+ kf = 1;
2396
+ kl = minp;
2397
+
2398
+ //
2399
+ // If IJOB=2, initialize C.
2400
+ // If IJOB=3, use the user-supplied starting point.
2401
+ //
2402
+ if( ijob==2 )
2403
+ {
2404
+ for(ji = 1; ji <= minp; ji++)
2405
+ {
2406
+ c(ji) = 0.5*(ab(ji,1)+ab(ji,2));
2407
+ }
2408
+ }
2409
+
2410
+ //
2411
+ // Iteration loop
2412
+ //
2413
+ for(jit = 1; jit <= nitmax; jit++)
2414
+ {
2415
+
2416
+ //
2417
+ // Loop over intervals
2418
+ //
2419
+ //
2420
+ // Serial Version of the loop
2421
+ //
2422
+ klnew = kl;
2423
+ for(ji = kf; ji <= kl; ji++)
2424
+ {
2425
+
2426
+ //
2427
+ // Compute N(w), the number of eigenvalues less than w
2428
+ //
2429
+ tmp1 = c(ji);
2430
+ tmp2 = d(1)-tmp1;
2431
+ itmp1 = 0;
2432
+ if( tmp2<=pivmin )
2433
+ {
2434
+ itmp1 = 1;
2435
+ tmp2 = ap::minreal(tmp2, -pivmin);
2436
+ }
2437
+
2438
+ //
2439
+ // A series of compiler directives to defeat vectorization
2440
+ // for the next loop
2441
+ //
2442
+ //*$PL$ CMCHAR=' '
2443
+ //CDIR$ NEXTSCALAR
2444
+ //C$DIR SCALAR
2445
+ //CDIR$ NEXT SCALAR
2446
+ //CVD$L NOVECTOR
2447
+ //CDEC$ NOVECTOR
2448
+ //CVD$ NOVECTOR
2449
+ //*VDIR NOVECTOR
2450
+ //*VOCL LOOP,SCALAR
2451
+ //CIBM PREFER SCALAR
2452
+ //*$PL$ CMCHAR='*'
2453
+ //
2454
+ for(j = 2; j <= n; j++)
2455
+ {
2456
+ tmp2 = d(j)-e2(j-1)/tmp2-tmp1;
2457
+ if( tmp2<=pivmin )
2458
+ {
2459
+ itmp1 = itmp1+1;
2460
+ tmp2 = ap::minreal(tmp2, -pivmin);
2461
+ }
2462
+ }
2463
+ if( ijob<=2 )
2464
+ {
2465
+
2466
+ //
2467
+ // IJOB=2: Choose all intervals containing eigenvalues.
2468
+ //
2469
+ // Insure that N(w) is monotone
2470
+ //
2471
+ itmp1 = ap::minint(nab(ji,2), ap::maxint(nab(ji,1), itmp1));
2472
+
2473
+ //
2474
+ // Update the Queue -- add intervals if both halves
2475
+ // contain eigenvalues.
2476
+ //
2477
+ if( itmp1==nab(ji,2) )
2478
+ {
2479
+
2480
+ //
2481
+ // No eigenvalue in the upper interval:
2482
+ // just use the lower interval.
2483
+ //
2484
+ ab(ji,2) = tmp1;
2485
+ }
2486
+ else
2487
+ {
2488
+ if( itmp1==nab(ji,1) )
2489
+ {
2490
+
2491
+ //
2492
+ // No eigenvalue in the lower interval:
2493
+ // just use the upper interval.
2494
+ //
2495
+ ab(ji,1) = tmp1;
2496
+ }
2497
+ else
2498
+ {
2499
+ if( klnew<mmax )
2500
+ {
2501
+
2502
+ //
2503
+ // Eigenvalue in both intervals -- add upper to queue.
2504
+ //
2505
+ klnew = klnew+1;
2506
+ ab(klnew,2) = ab(ji,2);
2507
+ nab(klnew,2) = nab(ji,2);
2508
+ ab(klnew,1) = tmp1;
2509
+ nab(klnew,1) = itmp1;
2510
+ ab(ji,2) = tmp1;
2511
+ nab(ji,2) = itmp1;
2512
+ }
2513
+ else
2514
+ {
2515
+ info = mmax+1;
2516
+ return;
2517
+ }
2518
+ }
2519
+ }
2520
+ }
2521
+ else
2522
+ {
2523
+
2524
+ //
2525
+ // IJOB=3: Binary search. Keep only the interval
2526
+ // containing w s.t. N(w) = NVAL
2527
+ //
2528
+ if( itmp1<=nval(ji) )
2529
+ {
2530
+ ab(ji,1) = tmp1;
2531
+ nab(ji,1) = itmp1;
2532
+ }
2533
+ if( itmp1>=nval(ji) )
2534
+ {
2535
+ ab(ji,2) = tmp1;
2536
+ nab(ji,2) = itmp1;
2537
+ }
2538
+ }
2539
+ }
2540
+ kl = klnew;
2541
+
2542
+ //
2543
+ // Check for convergence
2544
+ //
2545
+ kfnew = kf;
2546
+ for(ji = kf; ji <= kl; ji++)
2547
+ {
2548
+ tmp1 = fabs(ab(ji,2)-ab(ji,1));
2549
+ tmp2 = ap::maxreal(fabs(ab(ji,2)), fabs(ab(ji,1)));
2550
+ if( tmp1<ap::maxreal(abstol, ap::maxreal(pivmin, reltol*tmp2))||nab(ji,1)>=nab(ji,2) )
2551
+ {
2552
+
2553
+ //
2554
+ // Converged -- Swap with position KFNEW,
2555
+ // then increment KFNEW
2556
+ //
2557
+ if( ji>kfnew )
2558
+ {
2559
+ tmp1 = ab(ji,1);
2560
+ tmp2 = ab(ji,2);
2561
+ itmp1 = nab(ji,1);
2562
+ itmp2 = nab(ji,2);
2563
+ ab(ji,1) = ab(kfnew,1);
2564
+ ab(ji,2) = ab(kfnew,2);
2565
+ nab(ji,1) = nab(kfnew,1);
2566
+ nab(ji,2) = nab(kfnew,2);
2567
+ ab(kfnew,1) = tmp1;
2568
+ ab(kfnew,2) = tmp2;
2569
+ nab(kfnew,1) = itmp1;
2570
+ nab(kfnew,2) = itmp2;
2571
+ if( ijob==3 )
2572
+ {
2573
+ itmp1 = nval(ji);
2574
+ nval(ji) = nval(kfnew);
2575
+ nval(kfnew) = itmp1;
2576
+ }
2577
+ }
2578
+ kfnew = kfnew+1;
2579
+ }
2580
+ }
2581
+ kf = kfnew;
2582
+
2583
+ //
2584
+ // Choose Midpoints
2585
+ //
2586
+ for(ji = kf; ji <= kl; ji++)
2587
+ {
2588
+ c(ji) = 0.5*(ab(ji,1)+ab(ji,2));
2589
+ }
2590
+
2591
+ //
2592
+ // If no more intervals to refine, quit.
2593
+ //
2594
+ if( kf>kl )
2595
+ {
2596
+ break;
2597
+ }
2598
+ }
2599
+
2600
+ //
2601
+ // Converged
2602
+ //
2603
+ info = ap::maxint(kl+1-kf, 0);
2604
+ mout = kl;
2605
+ }
2606
+
2607
+
2608
+