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,228 @@
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
+ #ifndef _tdbisinv_h
40
+ #define _tdbisinv_h
41
+
42
+ #include "ap.h"
43
+ #include "ialglib.h"
44
+
45
+ #include "blas.h"
46
+
47
+
48
+ /*************************************************************************
49
+ Subroutine for finding the tridiagonal matrix eigenvalues/vectors in a
50
+ given half-interval (A, B] by using bisection and inverse iteration.
51
+
52
+ Input parameters:
53
+ D - the main diagonal of a tridiagonal matrix.
54
+ Array whose index ranges within [0..N-1].
55
+ E - the secondary diagonal of a tridiagonal matrix.
56
+ Array whose index ranges within [0..N-2].
57
+ N - size of matrix, N>=0.
58
+ ZNeeded - flag controlling whether the eigenvectors are needed or not.
59
+ If ZNeeded is equal to:
60
+ * 0, the eigenvectors are not needed;
61
+ * 1, the eigenvectors of a tridiagonal matrix are multiplied
62
+ by the square matrix Z. It is used if the tridiagonal
63
+ matrix is obtained by the similarity transformation
64
+ of a symmetric matrix.
65
+ * 2, the eigenvectors of a tridiagonal matrix replace matrix Z.
66
+ A, B - half-interval (A, B] to search eigenvalues in.
67
+ Z - if ZNeeded is equal to:
68
+ * 0, Z isn't used and remains unchanged;
69
+ * 1, Z contains the square matrix (array whose indexes range
70
+ within [0..N-1, 0..N-1]) which reduces the given symmetric
71
+ matrix to tridiagonal form;
72
+ * 2, Z isn't used (but changed on the exit).
73
+
74
+ Output parameters:
75
+ D - array of the eigenvalues found.
76
+ Array whose index ranges within [0..M-1].
77
+ M - number of eigenvalues found in the given half-interval (M>=0).
78
+ Z - if ZNeeded is equal to:
79
+ * 0, doesn't contain any information;
80
+ * 1, contains the product of a given NxN matrix Z (from the
81
+ left) and NxM matrix of the eigenvectors found (from the
82
+ right). Array whose indexes range within [0..N-1, 0..M-1].
83
+ * 2, contains the matrix of the eigenvectors found.
84
+ Array whose indexes range within [0..N-1, 0..M-1].
85
+
86
+ Result:
87
+
88
+ True, if successful. In that case, M contains the number of eigenvalues
89
+ in the given half-interval (could be equal to 0), D contains the eigenvalues,
90
+ Z contains the eigenvectors (if needed).
91
+ It should be noted that the subroutine changes the size of arrays D and Z.
92
+
93
+ False, if the bisection method subroutine wasn't able to find the
94
+ eigenvalues in the given interval or if the inverse iteration subroutine
95
+ wasn't able to find all the corresponding eigenvectors. In that case,
96
+ the eigenvalues and eigenvectors are not returned, M is equal to 0.
97
+
98
+ -- ALGLIB --
99
+ Copyright 31.03.2008 by Bochkanov Sergey
100
+ *************************************************************************/
101
+ bool smatrixtdevdr(ap::real_1d_array& d,
102
+ const ap::real_1d_array& e,
103
+ int n,
104
+ int zneeded,
105
+ double a,
106
+ double b,
107
+ int& m,
108
+ ap::real_2d_array& z);
109
+
110
+
111
+ /*************************************************************************
112
+ Subroutine for finding tridiagonal matrix eigenvalues/vectors with given
113
+ indexes (in ascending order) by using the bisection and inverse iteraion.
114
+
115
+ Input parameters:
116
+ D - the main diagonal of a tridiagonal matrix.
117
+ Array whose index ranges within [0..N-1].
118
+ E - the secondary diagonal of a tridiagonal matrix.
119
+ Array whose index ranges within [0..N-2].
120
+ N - size of matrix. N>=0.
121
+ ZNeeded - flag controlling whether the eigenvectors are needed or not.
122
+ If ZNeeded is equal to:
123
+ * 0, the eigenvectors are not needed;
124
+ * 1, the eigenvectors of a tridiagonal matrix are multiplied
125
+ by the square matrix Z. It is used if the
126
+ tridiagonal matrix is obtained by the similarity transformation
127
+ of a symmetric matrix.
128
+ * 2, the eigenvectors of a tridiagonal matrix replace
129
+ matrix Z.
130
+ I1, I2 - index interval for searching (from I1 to I2).
131
+ 0 <= I1 <= I2 <= N-1.
132
+ Z - if ZNeeded is equal to:
133
+ * 0, Z isn't used and remains unchanged;
134
+ * 1, Z contains the square matrix (array whose indexes range within [0..N-1, 0..N-1])
135
+ which reduces the given symmetric matrix to tridiagonal form;
136
+ * 2, Z isn't used (but changed on the exit).
137
+
138
+ Output parameters:
139
+ D - array of the eigenvalues found.
140
+ Array whose index ranges within [0..I2-I1].
141
+ Z - if ZNeeded is equal to:
142
+ * 0, doesn't contain any information;
143
+ * 1, contains the product of a given NxN matrix Z (from the left) and
144
+ Nx(I2-I1) matrix of the eigenvectors found (from the right).
145
+ Array whose indexes range within [0..N-1, 0..I2-I1].
146
+ * 2, contains the matrix of the eigenvalues found.
147
+ Array whose indexes range within [0..N-1, 0..I2-I1].
148
+
149
+
150
+ Result:
151
+
152
+ True, if successful. In that case, D contains the eigenvalues,
153
+ Z contains the eigenvectors (if needed).
154
+ It should be noted that the subroutine changes the size of arrays D and Z.
155
+
156
+ False, if the bisection method subroutine wasn't able to find the eigenvalues
157
+ in the given interval or if the inverse iteration subroutine wasn't able
158
+ to find all the corresponding eigenvectors. In that case, the eigenvalues
159
+ and eigenvectors are not returned.
160
+
161
+ -- ALGLIB --
162
+ Copyright 25.12.2005 by Bochkanov Sergey
163
+ *************************************************************************/
164
+ bool smatrixtdevdi(ap::real_1d_array& d,
165
+ const ap::real_1d_array& e,
166
+ int n,
167
+ int zneeded,
168
+ int i1,
169
+ int i2,
170
+ ap::real_2d_array& z);
171
+
172
+
173
+ /*************************************************************************
174
+ Obsolete 1-based subroutine
175
+ *************************************************************************/
176
+ bool tridiagonaleigenvaluesandvectorsininterval(ap::real_1d_array& d,
177
+ const ap::real_1d_array& e,
178
+ int n,
179
+ int zneeded,
180
+ double a,
181
+ double b,
182
+ int& m,
183
+ ap::real_2d_array& z);
184
+
185
+
186
+ /*************************************************************************
187
+ Obsolete 1-based subroutine
188
+ *************************************************************************/
189
+ bool tridiagonaleigenvaluesandvectorsbyindexes(ap::real_1d_array& d,
190
+ const ap::real_1d_array& e,
191
+ int n,
192
+ int zneeded,
193
+ int i1,
194
+ int i2,
195
+ ap::real_2d_array& z);
196
+
197
+
198
+ bool internalbisectioneigenvalues(ap::real_1d_array d,
199
+ ap::real_1d_array e,
200
+ int n,
201
+ int irange,
202
+ int iorder,
203
+ double vl,
204
+ double vu,
205
+ int il,
206
+ int iu,
207
+ double abstol,
208
+ ap::real_1d_array& w,
209
+ int& m,
210
+ int& nsplit,
211
+ ap::integer_1d_array& iblock,
212
+ ap::integer_1d_array& isplit,
213
+ int& errorcode);
214
+
215
+
216
+ void internaldstein(const int& n,
217
+ const ap::real_1d_array& d,
218
+ ap::real_1d_array e,
219
+ const int& m,
220
+ ap::real_1d_array w,
221
+ const ap::integer_1d_array& iblock,
222
+ const ap::integer_1d_array& isplit,
223
+ ap::real_2d_array& z,
224
+ ap::integer_1d_array& ifail,
225
+ int& info);
226
+
227
+
228
+ #endif
@@ -0,0 +1,1229 @@
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 "tdevd.h"
41
+
42
+ static void tdevde2(const double& a,
43
+ const double& b,
44
+ const double& c,
45
+ double& rt1,
46
+ double& rt2);
47
+ static void tdevdev2(const double& a,
48
+ const double& b,
49
+ const double& c,
50
+ double& rt1,
51
+ double& rt2,
52
+ double& cs1,
53
+ double& sn1);
54
+ static double tdevdpythag(double a, double b);
55
+ static double tdevdextsign(double a, double b);
56
+
57
+ /*************************************************************************
58
+ Finding the eigenvalues and eigenvectors of a tridiagonal symmetric matrix
59
+
60
+ The algorithm finds the eigen pairs of a tridiagonal symmetric matrix by
61
+ using an QL/QR algorithm with implicit shifts.
62
+
63
+ Input parameters:
64
+ D - the main diagonal of a tridiagonal matrix.
65
+ Array whose index ranges within [0..N-1].
66
+ E - the secondary diagonal of a tridiagonal matrix.
67
+ Array whose index ranges within [0..N-2].
68
+ N - size of matrix A.
69
+ ZNeeded - flag controlling whether the eigenvectors are needed or not.
70
+ If ZNeeded is equal to:
71
+ * 0, the eigenvectors are not needed;
72
+ * 1, the eigenvectors of a tridiagonal matrix
73
+ are multiplied by the square matrix Z. It is used if the
74
+ tridiagonal matrix is obtained by the similarity
75
+ transformation of a symmetric matrix;
76
+ * 2, the eigenvectors of a tridiagonal matrix replace the
77
+ square matrix Z;
78
+ * 3, matrix Z contains the first row of the eigenvectors
79
+ matrix.
80
+ Z - if ZNeeded=1, Z contains the square matrix by which the
81
+ eigenvectors are multiplied.
82
+ Array whose indexes range within [0..N-1, 0..N-1].
83
+
84
+ Output parameters:
85
+ D - eigenvalues in ascending order.
86
+ Array whose index ranges within [0..N-1].
87
+ Z - if ZNeeded is equal to:
88
+ * 0, Z hasn�t changed;
89
+ * 1, Z contains the product of a given matrix (from the left)
90
+ and the eigenvectors matrix (from the right);
91
+ * 2, Z contains the eigenvectors.
92
+ * 3, Z contains the first row of the eigenvectors matrix.
93
+ If ZNeeded<3, Z is the array whose indexes range within [0..N-1, 0..N-1].
94
+ In that case, the eigenvectors are stored in the matrix columns.
95
+ If ZNeeded=3, Z is the array whose indexes range within [0..0, 0..N-1].
96
+
97
+ Result:
98
+ True, if the algorithm has converged.
99
+ False, if the algorithm hasn't converged.
100
+
101
+ -- LAPACK routine (version 3.0) --
102
+ Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
103
+ Courant Institute, Argonne National Lab, and Rice University
104
+ September 30, 1994
105
+ *************************************************************************/
106
+ bool smatrixtdevd(ap::real_1d_array& d,
107
+ ap::real_1d_array e,
108
+ int n,
109
+ int zneeded,
110
+ ap::real_2d_array& z)
111
+ {
112
+ bool result;
113
+ ap::real_1d_array d1;
114
+ ap::real_1d_array e1;
115
+ ap::real_2d_array z1;
116
+ int i;
117
+
118
+
119
+ //
120
+ // Prepare 1-based task
121
+ //
122
+ d1.setbounds(1, n);
123
+ e1.setbounds(1, n);
124
+ ap::vmove(&d1(1), &d(0), ap::vlen(1,n));
125
+ if( n>1 )
126
+ {
127
+ ap::vmove(&e1(1), &e(0), ap::vlen(1,n-1));
128
+ }
129
+ if( zneeded==1 )
130
+ {
131
+ z1.setbounds(1, n, 1, n);
132
+ for(i = 1; i <= n; i++)
133
+ {
134
+ ap::vmove(&z1(i, 1), &z(i-1, 0), ap::vlen(1,n));
135
+ }
136
+ }
137
+
138
+ //
139
+ // Solve 1-based task
140
+ //
141
+ result = tridiagonalevd(d1, e1, n, zneeded, z1);
142
+ if( !result )
143
+ {
144
+ return result;
145
+ }
146
+
147
+ //
148
+ // Convert back to 0-based result
149
+ //
150
+ ap::vmove(&d(0), &d1(1), ap::vlen(0,n-1));
151
+ if( zneeded!=0 )
152
+ {
153
+ if( zneeded==1 )
154
+ {
155
+ for(i = 1; i <= n; i++)
156
+ {
157
+ ap::vmove(&z(i-1, 0), &z1(i, 1), ap::vlen(0,n-1));
158
+ }
159
+ return result;
160
+ }
161
+ if( zneeded==2 )
162
+ {
163
+ z.setbounds(0, n-1, 0, n-1);
164
+ for(i = 1; i <= n; i++)
165
+ {
166
+ ap::vmove(&z(i-1, 0), &z1(i, 1), ap::vlen(0,n-1));
167
+ }
168
+ return result;
169
+ }
170
+ if( zneeded==3 )
171
+ {
172
+ z.setbounds(0, 0, 0, n-1);
173
+ ap::vmove(&z(0, 0), &z1(1, 1), ap::vlen(0,n-1));
174
+ return result;
175
+ }
176
+ ap::ap_error::make_assertion(false, "SMatrixTDEVD: Incorrect ZNeeded!");
177
+ }
178
+ return result;
179
+ }
180
+
181
+
182
+ /*************************************************************************
183
+ Obsolete 1-based subroutine.
184
+ *************************************************************************/
185
+ bool tridiagonalevd(ap::real_1d_array& d,
186
+ ap::real_1d_array e,
187
+ int n,
188
+ int zneeded,
189
+ ap::real_2d_array& z)
190
+ {
191
+ bool result;
192
+ int maxit;
193
+ int i;
194
+ int icompz;
195
+ int ii;
196
+ int iscale;
197
+ int j;
198
+ int jtot;
199
+ int k;
200
+ int t;
201
+ int l;
202
+ int l1;
203
+ int lend;
204
+ int lendm1;
205
+ int lendp1;
206
+ int lendsv;
207
+ int lm1;
208
+ int lsv;
209
+ int m;
210
+ int mm;
211
+ int mm1;
212
+ int nm1;
213
+ int nmaxit;
214
+ int tmpint;
215
+ double anorm;
216
+ double b;
217
+ double c;
218
+ double eps;
219
+ double eps2;
220
+ double f;
221
+ double g;
222
+ double p;
223
+ double r;
224
+ double rt1;
225
+ double rt2;
226
+ double s;
227
+ double safmax;
228
+ double safmin;
229
+ double ssfmax;
230
+ double ssfmin;
231
+ double tst;
232
+ double tmp;
233
+ ap::real_1d_array work1;
234
+ ap::real_1d_array work2;
235
+ ap::real_1d_array workc;
236
+ ap::real_1d_array works;
237
+ ap::real_1d_array wtemp;
238
+ bool gotoflag;
239
+ int zrows;
240
+ bool wastranspose;
241
+
242
+ ap::ap_error::make_assertion(zneeded>=0&&zneeded<=3, "TridiagonalEVD: Incorrent ZNeeded");
243
+
244
+ //
245
+ // Quick return if possible
246
+ //
247
+ if( zneeded<0||zneeded>3 )
248
+ {
249
+ result = false;
250
+ return result;
251
+ }
252
+ result = true;
253
+ if( n==0 )
254
+ {
255
+ return result;
256
+ }
257
+ if( n==1 )
258
+ {
259
+ if( zneeded==2||zneeded==3 )
260
+ {
261
+ z.setbounds(1, 1, 1, 1);
262
+ z(1,1) = 1;
263
+ }
264
+ return result;
265
+ }
266
+ maxit = 30;
267
+
268
+ //
269
+ // Initialize arrays
270
+ //
271
+ wtemp.setbounds(1, n);
272
+ work1.setbounds(1, n-1);
273
+ work2.setbounds(1, n-1);
274
+ workc.setbounds(1, n);
275
+ works.setbounds(1, n);
276
+
277
+ //
278
+ // Determine the unit roundoff and over/underflow thresholds.
279
+ //
280
+ eps = ap::machineepsilon;
281
+ eps2 = ap::sqr(eps);
282
+ safmin = ap::minrealnumber;
283
+ safmax = ap::maxrealnumber;
284
+ ssfmax = sqrt(safmax)/3;
285
+ ssfmin = sqrt(safmin)/eps2;
286
+
287
+ //
288
+ // Prepare Z
289
+ //
290
+ // Here we are using transposition to get rid of column operations
291
+ //
292
+ //
293
+ wastranspose = false;
294
+ if( zneeded==0 )
295
+ {
296
+ zrows = 0;
297
+ }
298
+ if( zneeded==1 )
299
+ {
300
+ zrows = n;
301
+ }
302
+ if( zneeded==2 )
303
+ {
304
+ zrows = n;
305
+ }
306
+ if( zneeded==3 )
307
+ {
308
+ zrows = 1;
309
+ }
310
+ if( zneeded==1 )
311
+ {
312
+ wastranspose = true;
313
+ inplacetranspose(z, 1, n, 1, n, wtemp);
314
+ }
315
+ if( zneeded==2 )
316
+ {
317
+ wastranspose = true;
318
+ z.setbounds(1, n, 1, n);
319
+ for(i = 1; i <= n; i++)
320
+ {
321
+ for(j = 1; j <= n; j++)
322
+ {
323
+ if( i==j )
324
+ {
325
+ z(i,j) = 1;
326
+ }
327
+ else
328
+ {
329
+ z(i,j) = 0;
330
+ }
331
+ }
332
+ }
333
+ }
334
+ if( zneeded==3 )
335
+ {
336
+ wastranspose = false;
337
+ z.setbounds(1, 1, 1, n);
338
+ for(j = 1; j <= n; j++)
339
+ {
340
+ if( j==1 )
341
+ {
342
+ z(1,j) = 1;
343
+ }
344
+ else
345
+ {
346
+ z(1,j) = 0;
347
+ }
348
+ }
349
+ }
350
+ nmaxit = n*maxit;
351
+ jtot = 0;
352
+
353
+ //
354
+ // Determine where the matrix splits and choose QL or QR iteration
355
+ // for each block, according to whether top or bottom diagonal
356
+ // element is smaller.
357
+ //
358
+ l1 = 1;
359
+ nm1 = n-1;
360
+ while(true)
361
+ {
362
+ if( l1>n )
363
+ {
364
+ break;
365
+ }
366
+ if( l1>1 )
367
+ {
368
+ e(l1-1) = 0;
369
+ }
370
+ gotoflag = false;
371
+ if( l1<=nm1 )
372
+ {
373
+ for(m = l1; m <= nm1; m++)
374
+ {
375
+ tst = fabs(e(m));
376
+ if( tst==0 )
377
+ {
378
+ gotoflag = true;
379
+ break;
380
+ }
381
+ if( tst<=sqrt(fabs(d(m)))*sqrt(fabs(d(m+1)))*eps )
382
+ {
383
+ e(m) = 0;
384
+ gotoflag = true;
385
+ break;
386
+ }
387
+ }
388
+ }
389
+ if( !gotoflag )
390
+ {
391
+ m = n;
392
+ }
393
+
394
+ //
395
+ // label 30:
396
+ //
397
+ l = l1;
398
+ lsv = l;
399
+ lend = m;
400
+ lendsv = lend;
401
+ l1 = m+1;
402
+ if( lend==l )
403
+ {
404
+ continue;
405
+ }
406
+
407
+ //
408
+ // Scale submatrix in rows and columns L to LEND
409
+ //
410
+ if( l==lend )
411
+ {
412
+ anorm = fabs(d(l));
413
+ }
414
+ else
415
+ {
416
+ anorm = ap::maxreal(fabs(d(l))+fabs(e(l)), fabs(e(lend-1))+fabs(d(lend)));
417
+ for(i = l+1; i <= lend-1; i++)
418
+ {
419
+ anorm = ap::maxreal(anorm, fabs(d(i))+fabs(e(i))+fabs(e(i-1)));
420
+ }
421
+ }
422
+ iscale = 0;
423
+ if( anorm==0 )
424
+ {
425
+ continue;
426
+ }
427
+ if( anorm>ssfmax )
428
+ {
429
+ iscale = 1;
430
+ tmp = ssfmax/anorm;
431
+ tmpint = lend-1;
432
+ ap::vmul(&d(l), ap::vlen(l,lend), tmp);
433
+ ap::vmul(&e(l), ap::vlen(l,tmpint), tmp);
434
+ }
435
+ if( anorm<ssfmin )
436
+ {
437
+ iscale = 2;
438
+ tmp = ssfmin/anorm;
439
+ tmpint = lend-1;
440
+ ap::vmul(&d(l), ap::vlen(l,lend), tmp);
441
+ ap::vmul(&e(l), ap::vlen(l,tmpint), tmp);
442
+ }
443
+
444
+ //
445
+ // Choose between QL and QR iteration
446
+ //
447
+ if( fabs(d(lend))<fabs(d(l)) )
448
+ {
449
+ lend = lsv;
450
+ l = lendsv;
451
+ }
452
+ if( lend>l )
453
+ {
454
+
455
+ //
456
+ // QL Iteration
457
+ //
458
+ // Look for small subdiagonal element.
459
+ //
460
+ while(true)
461
+ {
462
+ gotoflag = false;
463
+ if( l!=lend )
464
+ {
465
+ lendm1 = lend-1;
466
+ for(m = l; m <= lendm1; m++)
467
+ {
468
+ tst = ap::sqr(fabs(e(m)));
469
+ if( tst<=eps2*fabs(d(m))*fabs(d(m+1))+safmin )
470
+ {
471
+ gotoflag = true;
472
+ break;
473
+ }
474
+ }
475
+ }
476
+ if( !gotoflag )
477
+ {
478
+ m = lend;
479
+ }
480
+ if( m<lend )
481
+ {
482
+ e(m) = 0;
483
+ }
484
+ p = d(l);
485
+ if( m!=l )
486
+ {
487
+
488
+ //
489
+ // If remaining matrix is 2-by-2, use DLAE2 or SLAEV2
490
+ // to compute its eigensystem.
491
+ //
492
+ if( m==l+1 )
493
+ {
494
+ if( zneeded>0 )
495
+ {
496
+ tdevdev2(d(l), e(l), d(l+1), rt1, rt2, c, s);
497
+ work1(l) = c;
498
+ work2(l) = s;
499
+ workc(1) = work1(l);
500
+ works(1) = work2(l);
501
+ if( !wastranspose )
502
+ {
503
+ applyrotationsfromtheright(false, 1, zrows, l, l+1, workc, works, z, wtemp);
504
+ }
505
+ else
506
+ {
507
+ applyrotationsfromtheleft(false, l, l+1, 1, zrows, workc, works, z, wtemp);
508
+ }
509
+ }
510
+ else
511
+ {
512
+ tdevde2(d(l), e(l), d(l+1), rt1, rt2);
513
+ }
514
+ d(l) = rt1;
515
+ d(l+1) = rt2;
516
+ e(l) = 0;
517
+ l = l+2;
518
+ if( l<=lend )
519
+ {
520
+ continue;
521
+ }
522
+
523
+ //
524
+ // GOTO 140
525
+ //
526
+ break;
527
+ }
528
+ if( jtot==nmaxit )
529
+ {
530
+
531
+ //
532
+ // GOTO 140
533
+ //
534
+ break;
535
+ }
536
+ jtot = jtot+1;
537
+
538
+ //
539
+ // Form shift.
540
+ //
541
+ g = (d(l+1)-p)/(2*e(l));
542
+ r = tdevdpythag(g, double(1));
543
+ g = d(m)-p+e(l)/(g+tdevdextsign(r, g));
544
+ s = 1;
545
+ c = 1;
546
+ p = 0;
547
+
548
+ //
549
+ // Inner loop
550
+ //
551
+ mm1 = m-1;
552
+ for(i = mm1; i >= l; i--)
553
+ {
554
+ f = s*e(i);
555
+ b = c*e(i);
556
+ generaterotation(g, f, c, s, r);
557
+ if( i!=m-1 )
558
+ {
559
+ e(i+1) = r;
560
+ }
561
+ g = d(i+1)-p;
562
+ r = (d(i)-g)*s+2*c*b;
563
+ p = s*r;
564
+ d(i+1) = g+p;
565
+ g = c*r-b;
566
+
567
+ //
568
+ // If eigenvectors are desired, then save rotations.
569
+ //
570
+ if( zneeded>0 )
571
+ {
572
+ work1(i) = c;
573
+ work2(i) = -s;
574
+ }
575
+ }
576
+
577
+ //
578
+ // If eigenvectors are desired, then apply saved rotations.
579
+ //
580
+ if( zneeded>0 )
581
+ {
582
+ for(i = l; i <= m-1; i++)
583
+ {
584
+ workc(i-l+1) = work1(i);
585
+ works(i-l+1) = work2(i);
586
+ }
587
+ if( !wastranspose )
588
+ {
589
+ applyrotationsfromtheright(false, 1, zrows, l, m, workc, works, z, wtemp);
590
+ }
591
+ else
592
+ {
593
+ applyrotationsfromtheleft(false, l, m, 1, zrows, workc, works, z, wtemp);
594
+ }
595
+ }
596
+ d(l) = d(l)-p;
597
+ e(l) = g;
598
+ continue;
599
+ }
600
+
601
+ //
602
+ // Eigenvalue found.
603
+ //
604
+ d(l) = p;
605
+ l = l+1;
606
+ if( l<=lend )
607
+ {
608
+ continue;
609
+ }
610
+ break;
611
+ }
612
+ }
613
+ else
614
+ {
615
+
616
+ //
617
+ // QR Iteration
618
+ //
619
+ // Look for small superdiagonal element.
620
+ //
621
+ while(true)
622
+ {
623
+ gotoflag = false;
624
+ if( l!=lend )
625
+ {
626
+ lendp1 = lend+1;
627
+ for(m = l; m >= lendp1; m--)
628
+ {
629
+ tst = ap::sqr(fabs(e(m-1)));
630
+ if( tst<=eps2*fabs(d(m))*fabs(d(m-1))+safmin )
631
+ {
632
+ gotoflag = true;
633
+ break;
634
+ }
635
+ }
636
+ }
637
+ if( !gotoflag )
638
+ {
639
+ m = lend;
640
+ }
641
+ if( m>lend )
642
+ {
643
+ e(m-1) = 0;
644
+ }
645
+ p = d(l);
646
+ if( m!=l )
647
+ {
648
+
649
+ //
650
+ // If remaining matrix is 2-by-2, use DLAE2 or SLAEV2
651
+ // to compute its eigensystem.
652
+ //
653
+ if( m==l-1 )
654
+ {
655
+ if( zneeded>0 )
656
+ {
657
+ tdevdev2(d(l-1), e(l-1), d(l), rt1, rt2, c, s);
658
+ work1(m) = c;
659
+ work2(m) = s;
660
+ workc(1) = c;
661
+ works(1) = s;
662
+ if( !wastranspose )
663
+ {
664
+ applyrotationsfromtheright(true, 1, zrows, l-1, l, workc, works, z, wtemp);
665
+ }
666
+ else
667
+ {
668
+ applyrotationsfromtheleft(true, l-1, l, 1, zrows, workc, works, z, wtemp);
669
+ }
670
+ }
671
+ else
672
+ {
673
+ tdevde2(d(l-1), e(l-1), d(l), rt1, rt2);
674
+ }
675
+ d(l-1) = rt1;
676
+ d(l) = rt2;
677
+ e(l-1) = 0;
678
+ l = l-2;
679
+ if( l>=lend )
680
+ {
681
+ continue;
682
+ }
683
+ break;
684
+ }
685
+ if( jtot==nmaxit )
686
+ {
687
+ break;
688
+ }
689
+ jtot = jtot+1;
690
+
691
+ //
692
+ // Form shift.
693
+ //
694
+ g = (d(l-1)-p)/(2*e(l-1));
695
+ r = tdevdpythag(g, double(1));
696
+ g = d(m)-p+e(l-1)/(g+tdevdextsign(r, g));
697
+ s = 1;
698
+ c = 1;
699
+ p = 0;
700
+
701
+ //
702
+ // Inner loop
703
+ //
704
+ lm1 = l-1;
705
+ for(i = m; i <= lm1; i++)
706
+ {
707
+ f = s*e(i);
708
+ b = c*e(i);
709
+ generaterotation(g, f, c, s, r);
710
+ if( i!=m )
711
+ {
712
+ e(i-1) = r;
713
+ }
714
+ g = d(i)-p;
715
+ r = (d(i+1)-g)*s+2*c*b;
716
+ p = s*r;
717
+ d(i) = g+p;
718
+ g = c*r-b;
719
+
720
+ //
721
+ // If eigenvectors are desired, then save rotations.
722
+ //
723
+ if( zneeded>0 )
724
+ {
725
+ work1(i) = c;
726
+ work2(i) = s;
727
+ }
728
+ }
729
+
730
+ //
731
+ // If eigenvectors are desired, then apply saved rotations.
732
+ //
733
+ if( zneeded>0 )
734
+ {
735
+ mm = l-m+1;
736
+ for(i = m; i <= l-1; i++)
737
+ {
738
+ workc(i-m+1) = work1(i);
739
+ works(i-m+1) = work2(i);
740
+ }
741
+ if( !wastranspose )
742
+ {
743
+ applyrotationsfromtheright(true, 1, zrows, m, l, workc, works, z, wtemp);
744
+ }
745
+ else
746
+ {
747
+ applyrotationsfromtheleft(true, m, l, 1, zrows, workc, works, z, wtemp);
748
+ }
749
+ }
750
+ d(l) = d(l)-p;
751
+ e(lm1) = g;
752
+ continue;
753
+ }
754
+
755
+ //
756
+ // Eigenvalue found.
757
+ //
758
+ d(l) = p;
759
+ l = l-1;
760
+ if( l>=lend )
761
+ {
762
+ continue;
763
+ }
764
+ break;
765
+ }
766
+ }
767
+
768
+ //
769
+ // Undo scaling if necessary
770
+ //
771
+ if( iscale==1 )
772
+ {
773
+ tmp = anorm/ssfmax;
774
+ tmpint = lendsv-1;
775
+ ap::vmul(&d(lsv), ap::vlen(lsv,lendsv), tmp);
776
+ ap::vmul(&e(lsv), ap::vlen(lsv,tmpint), tmp);
777
+ }
778
+ if( iscale==2 )
779
+ {
780
+ tmp = anorm/ssfmin;
781
+ tmpint = lendsv-1;
782
+ ap::vmul(&d(lsv), ap::vlen(lsv,lendsv), tmp);
783
+ ap::vmul(&e(lsv), ap::vlen(lsv,tmpint), tmp);
784
+ }
785
+
786
+ //
787
+ // Check for no convergence to an eigenvalue after a total
788
+ // of N*MAXIT iterations.
789
+ //
790
+ if( jtot>=nmaxit )
791
+ {
792
+ result = false;
793
+ if( wastranspose )
794
+ {
795
+ inplacetranspose(z, 1, n, 1, n, wtemp);
796
+ }
797
+ return result;
798
+ }
799
+ }
800
+
801
+ //
802
+ // Order eigenvalues and eigenvectors.
803
+ //
804
+ if( zneeded==0 )
805
+ {
806
+
807
+ //
808
+ // Sort
809
+ //
810
+ if( n==1 )
811
+ {
812
+ return result;
813
+ }
814
+ if( n==2 )
815
+ {
816
+ if( d(1)>d(2) )
817
+ {
818
+ tmp = d(1);
819
+ d(1) = d(2);
820
+ d(2) = tmp;
821
+ }
822
+ return result;
823
+ }
824
+ i = 2;
825
+ do
826
+ {
827
+ t = i;
828
+ while(t!=1)
829
+ {
830
+ k = t/2;
831
+ if( d(k)>=d(t) )
832
+ {
833
+ t = 1;
834
+ }
835
+ else
836
+ {
837
+ tmp = d(k);
838
+ d(k) = d(t);
839
+ d(t) = tmp;
840
+ t = k;
841
+ }
842
+ }
843
+ i = i+1;
844
+ }
845
+ while(i<=n);
846
+ i = n-1;
847
+ do
848
+ {
849
+ tmp = d(i+1);
850
+ d(i+1) = d(1);
851
+ d(+1) = tmp;
852
+ t = 1;
853
+ while(t!=0)
854
+ {
855
+ k = 2*t;
856
+ if( k>i )
857
+ {
858
+ t = 0;
859
+ }
860
+ else
861
+ {
862
+ if( k<i )
863
+ {
864
+ if( d(k+1)>d(k) )
865
+ {
866
+ k = k+1;
867
+ }
868
+ }
869
+ if( d(t)>=d(k) )
870
+ {
871
+ t = 0;
872
+ }
873
+ else
874
+ {
875
+ tmp = d(k);
876
+ d(k) = d(t);
877
+ d(t) = tmp;
878
+ t = k;
879
+ }
880
+ }
881
+ }
882
+ i = i-1;
883
+ }
884
+ while(i>=1);
885
+ }
886
+ else
887
+ {
888
+
889
+ //
890
+ // Use Selection Sort to minimize swaps of eigenvectors
891
+ //
892
+ for(ii = 2; ii <= n; ii++)
893
+ {
894
+ i = ii-1;
895
+ k = i;
896
+ p = d(i);
897
+ for(j = ii; j <= n; j++)
898
+ {
899
+ if( d(j)<p )
900
+ {
901
+ k = j;
902
+ p = d(j);
903
+ }
904
+ }
905
+ if( k!=i )
906
+ {
907
+ d(k) = d(i);
908
+ d(i) = p;
909
+ if( wastranspose )
910
+ {
911
+ ap::vmove(&wtemp(1), &z(i, 1), ap::vlen(1,n));
912
+ ap::vmove(&z(i, 1), &z(k, 1), ap::vlen(1,n));
913
+ ap::vmove(&z(k, 1), &wtemp(1), ap::vlen(1,n));
914
+ }
915
+ else
916
+ {
917
+ ap::vmove(wtemp.getvector(1, zrows), z.getcolumn(i, 1, zrows));
918
+ ap::vmove(z.getcolumn(i, 1, zrows), z.getcolumn(k, 1, zrows));
919
+ ap::vmove(z.getcolumn(k, 1, zrows), wtemp.getvector(1, zrows));
920
+ }
921
+ }
922
+ }
923
+ if( wastranspose )
924
+ {
925
+ inplacetranspose(z, 1, n, 1, n, wtemp);
926
+ }
927
+ }
928
+ return result;
929
+ }
930
+
931
+
932
+ /*************************************************************************
933
+ DLAE2 computes the eigenvalues of a 2-by-2 symmetric matrix
934
+ [ A B ]
935
+ [ B C ].
936
+ On return, RT1 is the eigenvalue of larger absolute value, and RT2
937
+ is the eigenvalue of smaller absolute value.
938
+
939
+ -- LAPACK auxiliary routine (version 3.0) --
940
+ Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
941
+ Courant Institute, Argonne National Lab, and Rice University
942
+ October 31, 1992
943
+ *************************************************************************/
944
+ static void tdevde2(const double& a,
945
+ const double& b,
946
+ const double& c,
947
+ double& rt1,
948
+ double& rt2)
949
+ {
950
+ double ab;
951
+ double acmn;
952
+ double acmx;
953
+ double adf;
954
+ double df;
955
+ double rt;
956
+ double sm;
957
+ double tb;
958
+
959
+ sm = a+c;
960
+ df = a-c;
961
+ adf = fabs(df);
962
+ tb = b+b;
963
+ ab = fabs(tb);
964
+ if( fabs(a)>fabs(c) )
965
+ {
966
+ acmx = a;
967
+ acmn = c;
968
+ }
969
+ else
970
+ {
971
+ acmx = c;
972
+ acmn = a;
973
+ }
974
+ if( adf>ab )
975
+ {
976
+ rt = adf*sqrt(1+ap::sqr(ab/adf));
977
+ }
978
+ else
979
+ {
980
+ if( adf<ab )
981
+ {
982
+ rt = ab*sqrt(1+ap::sqr(adf/ab));
983
+ }
984
+ else
985
+ {
986
+
987
+ //
988
+ // Includes case AB=ADF=0
989
+ //
990
+ rt = ab*sqrt(double(2));
991
+ }
992
+ }
993
+ if( sm<0 )
994
+ {
995
+ rt1 = 0.5*(sm-rt);
996
+
997
+ //
998
+ // Order of execution important.
999
+ // To get fully accurate smaller eigenvalue,
1000
+ // next line needs to be executed in higher precision.
1001
+ //
1002
+ rt2 = acmx/rt1*acmn-b/rt1*b;
1003
+ }
1004
+ else
1005
+ {
1006
+ if( sm>0 )
1007
+ {
1008
+ rt1 = 0.5*(sm+rt);
1009
+
1010
+ //
1011
+ // Order of execution important.
1012
+ // To get fully accurate smaller eigenvalue,
1013
+ // next line needs to be executed in higher precision.
1014
+ //
1015
+ rt2 = acmx/rt1*acmn-b/rt1*b;
1016
+ }
1017
+ else
1018
+ {
1019
+
1020
+ //
1021
+ // Includes case RT1 = RT2 = 0
1022
+ //
1023
+ rt1 = 0.5*rt;
1024
+ rt2 = -0.5*rt;
1025
+ }
1026
+ }
1027
+ }
1028
+
1029
+
1030
+ /*************************************************************************
1031
+ DLAEV2 computes the eigendecomposition of a 2-by-2 symmetric matrix
1032
+
1033
+ [ A B ]
1034
+ [ B C ].
1035
+
1036
+ On return, RT1 is the eigenvalue of larger absolute value, RT2 is the
1037
+ eigenvalue of smaller absolute value, and (CS1,SN1) is the unit right
1038
+ eigenvector for RT1, giving the decomposition
1039
+
1040
+ [ CS1 SN1 ] [ A B ] [ CS1 -SN1 ] = [ RT1 0 ]
1041
+ [-SN1 CS1 ] [ B C ] [ SN1 CS1 ] [ 0 RT2 ].
1042
+
1043
+
1044
+ -- LAPACK auxiliary routine (version 3.0) --
1045
+ Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
1046
+ Courant Institute, Argonne National Lab, and Rice University
1047
+ October 31, 1992
1048
+ *************************************************************************/
1049
+ static void tdevdev2(const double& a,
1050
+ const double& b,
1051
+ const double& c,
1052
+ double& rt1,
1053
+ double& rt2,
1054
+ double& cs1,
1055
+ double& sn1)
1056
+ {
1057
+ int sgn1;
1058
+ int sgn2;
1059
+ double ab;
1060
+ double acmn;
1061
+ double acmx;
1062
+ double acs;
1063
+ double adf;
1064
+ double cs;
1065
+ double ct;
1066
+ double df;
1067
+ double rt;
1068
+ double sm;
1069
+ double tb;
1070
+ double tn;
1071
+
1072
+
1073
+ //
1074
+ // Compute the eigenvalues
1075
+ //
1076
+ sm = a+c;
1077
+ df = a-c;
1078
+ adf = fabs(df);
1079
+ tb = b+b;
1080
+ ab = fabs(tb);
1081
+ if( fabs(a)>fabs(c) )
1082
+ {
1083
+ acmx = a;
1084
+ acmn = c;
1085
+ }
1086
+ else
1087
+ {
1088
+ acmx = c;
1089
+ acmn = a;
1090
+ }
1091
+ if( adf>ab )
1092
+ {
1093
+ rt = adf*sqrt(1+ap::sqr(ab/adf));
1094
+ }
1095
+ else
1096
+ {
1097
+ if( adf<ab )
1098
+ {
1099
+ rt = ab*sqrt(1+ap::sqr(adf/ab));
1100
+ }
1101
+ else
1102
+ {
1103
+
1104
+ //
1105
+ // Includes case AB=ADF=0
1106
+ //
1107
+ rt = ab*sqrt(double(2));
1108
+ }
1109
+ }
1110
+ if( sm<0 )
1111
+ {
1112
+ rt1 = 0.5*(sm-rt);
1113
+ sgn1 = -1;
1114
+
1115
+ //
1116
+ // Order of execution important.
1117
+ // To get fully accurate smaller eigenvalue,
1118
+ // next line needs to be executed in higher precision.
1119
+ //
1120
+ rt2 = acmx/rt1*acmn-b/rt1*b;
1121
+ }
1122
+ else
1123
+ {
1124
+ if( sm>0 )
1125
+ {
1126
+ rt1 = 0.5*(sm+rt);
1127
+ sgn1 = 1;
1128
+
1129
+ //
1130
+ // Order of execution important.
1131
+ // To get fully accurate smaller eigenvalue,
1132
+ // next line needs to be executed in higher precision.
1133
+ //
1134
+ rt2 = acmx/rt1*acmn-b/rt1*b;
1135
+ }
1136
+ else
1137
+ {
1138
+
1139
+ //
1140
+ // Includes case RT1 = RT2 = 0
1141
+ //
1142
+ rt1 = 0.5*rt;
1143
+ rt2 = -0.5*rt;
1144
+ sgn1 = 1;
1145
+ }
1146
+ }
1147
+
1148
+ //
1149
+ // Compute the eigenvector
1150
+ //
1151
+ if( df>=0 )
1152
+ {
1153
+ cs = df+rt;
1154
+ sgn2 = 1;
1155
+ }
1156
+ else
1157
+ {
1158
+ cs = df-rt;
1159
+ sgn2 = -1;
1160
+ }
1161
+ acs = fabs(cs);
1162
+ if( acs>ab )
1163
+ {
1164
+ ct = -tb/cs;
1165
+ sn1 = 1/sqrt(1+ct*ct);
1166
+ cs1 = ct*sn1;
1167
+ }
1168
+ else
1169
+ {
1170
+ if( ab==0 )
1171
+ {
1172
+ cs1 = 1;
1173
+ sn1 = 0;
1174
+ }
1175
+ else
1176
+ {
1177
+ tn = -cs/tb;
1178
+ cs1 = 1/sqrt(1+tn*tn);
1179
+ sn1 = tn*cs1;
1180
+ }
1181
+ }
1182
+ if( sgn1==sgn2 )
1183
+ {
1184
+ tn = cs1;
1185
+ cs1 = -sn1;
1186
+ sn1 = tn;
1187
+ }
1188
+ }
1189
+
1190
+
1191
+ /*************************************************************************
1192
+ Internal routine
1193
+ *************************************************************************/
1194
+ static double tdevdpythag(double a, double b)
1195
+ {
1196
+ double result;
1197
+
1198
+ if( fabs(a)<fabs(b) )
1199
+ {
1200
+ result = fabs(b)*sqrt(1+ap::sqr(a/b));
1201
+ }
1202
+ else
1203
+ {
1204
+ result = fabs(a)*sqrt(1+ap::sqr(b/a));
1205
+ }
1206
+ return result;
1207
+ }
1208
+
1209
+
1210
+ /*************************************************************************
1211
+ Internal routine
1212
+ *************************************************************************/
1213
+ static double tdevdextsign(double a, double b)
1214
+ {
1215
+ double result;
1216
+
1217
+ if( b>=0 )
1218
+ {
1219
+ result = fabs(a);
1220
+ }
1221
+ else
1222
+ {
1223
+ result = -fabs(a);
1224
+ }
1225
+ return result;
1226
+ }
1227
+
1228
+
1229
+