SCALAPACK 2.2.2
LAPACK: Linear Algebra PACKage
Loading...
Searching...
No Matches
pdlaiect.c
Go to the documentation of this file.
1
2
3/* ---------------------------------------------------------------------
4*
5* -- ScaLAPACK routine (version 1.5) --
6* University of Tennessee, Knoxville, Oak Ridge National Laboratory,
7* and University of California, Berkeley.
8* May 1, 1997
9*
10* ---------------------------------------------------------------------
11*/
12
13/*
14 * Include Files
15 */
16#include "pxsyevx.h"
17#include "pblas.h"
18#include <stdio.h>
19#include <math.h>
20#define proto(x) ()
21
22
23void pdlasnbt_( Int *ieflag )
24{
25/*
26*
27* Purpose
28* =======
29*
30* pdalsnbt finds the position of the signbit of a double
31* double precision floating point number. This routine assumes IEEE
32* arithmetic, and hence, tests only the 32nd and 64th bits as
33* possibilities for the sign bit.
34*
35* Note : For this release, we assume that sizeof(int) is 4 bytes.
36*
37* Note : If a compile time flag (NO_IEEE) indicates that the
38* machine does not have IEEE arithmetic, IEFLAG = 0 is returned.
39*
40* Arguments
41* =========
42*
43* IEFLAG (output) INTEGER
44* This indicates the position of the signbit of any double
45* precision floating point number.
46* IEFLAG = 0 if the compile time flag, NO_IEEE, indicates
47* that the machine does not have IEEE arithmetic, or if
48* sizeof(int) is different from 4 bytes.
49* IEFLAG = 1 indicates that the sign bit is the 32nd
50* bit ( Big Endian ).
51* IEFLAG = 2 indicates that the sign bit is the 64th
52* bit ( Little Endian ).
53*
54* =====================================================================
55*
56* .. Local Scalars ..
57*/
58 double x;
59 Int negone=-1, errornum;
60 unsigned Int *ix;
61/* ..
62* .. Executable Statements ..
63*/
64
65#ifdef NO_IEEE
66 *ieflag = 0;
67#else
68 if(sizeof(Int) != 4){
69 *ieflag = 0;
70 return;
71 }
72 x = (double) -1.0;
73 ix = (unsigned Int *) &x;
74 if(( *ix == 0xbff00000) && ( *(ix+1) == 0x0) )
75 {
76 *ieflag = 1;
77 } else if(( *(ix+1) == 0xbff00000) && ( *ix == 0x0) ) {
78 *ieflag = 2;
79 } else {
80 *ieflag = 0;
81 }
82#endif
83}
84
85void pdlaiectb_( double *sigma, Int *n, double *d, Int *count )
86{
87/*
88*
89* Purpose
90* =======
91*
92* pdlaiectb computes the number of negative eigenvalues of (A- SIGMA I).
93* This implementation of the Sturm Sequence loop exploits IEEE Arithmetic
94* and has no conditionals in the innermost loop. To extract the signbit,
95* this routine assumes that the double precision word is stored in
96* "Big Endian" word order, i.e, the signbit is assumed to be bit 32.
97*
98* Note that all arguments are call-by-reference so that this routine
99* can be directly called from Fortran code.
100*
101* This is a ScaLAPACK internal subroutine and arguments are not
102* checked for unreasonable values.
103*
104* Arguments
105* =========
106*
107* SIGMA (input) DOUBLE PRECISION
108* The shift. pdlaiectb finds the number of eigenvalues
109* less than equal to SIGMA.
110*
111* N (input) INTEGER
112* The order of the tridiagonal matrix T. N >= 1.
113*
114* D (input) DOUBLE PRECISION array, dimension (2*N - 1)
115* Contains the diagonals and the squares of the off-diagonal
116* elements of the tridiagonal matrix T. These elements are
117* assumed to be interleaved in memory for better cache
118* performance. The diagonal entries of T are in the entries
119* D(1),D(3),...,D(2*N-1), while the squares of the off-diagonal
120* entries are D(2),D(4),...,D(2*N-2). To avoid overflow, the
121* matrix must be scaled so that its largest entry is no greater
122* than overflow**(1/2) * underflow**(1/4) in absolute value,
123* and for greatest accuracy, it should not be much smaller
124* than that.
125*
126* COUNT (output) INTEGER
127* The count of the number of eigenvalues of T less than or
128* equal to SIGMA.
129*
130* =====================================================================
131*
132* .. Local Scalars ..
133*/
134 double lsigma, tmp, *pd, *pe2;
135 Int i;
136/* ..
137* .. Executable Statements ..
138*/
139
140 lsigma = *sigma;
141 pd = d; pe2 = d+1;
142 tmp = *pd - lsigma; pd += 2;
143 *count = (*((Int *)&tmp) >> 31) & 1;
144 for(i = 1;i < *n;i++){
145 tmp = *pd - *pe2/tmp - lsigma;
146 pd += 2; pe2 += 2;
147 *count += ((*((Int *)&tmp)) >> 31) & 1;
148 }
149}
150
151void pdlaiectl_( double *sigma, Int *n, double *d, Int *count )
152{
153/*
154*
155* Purpose
156* =======
157*
158* pdlaiectl computes the number of negative eigenvalues of (A- SIGMA I).
159* This implementation of the Sturm Sequence loop exploits IEEE Arithmetic
160* and has no conditionals in the innermost loop. To extract the signbit,
161* this routine assumes that the double precision word is stored in
162* "Little Endian" word order, i.e, the signbit is assumed to be bit 64.
163*
164* Note that all arguments are call-by-reference so that this routine
165* can be directly called from Fortran code.
166*
167* This is a ScaLAPACK internal subroutine and arguments are not
168* checked for unreasonable values.
169*
170* Arguments
171* =========
172*
173* SIGMA (input) DOUBLE PRECISION
174* The shift. pdlaiectl finds the number of eigenvalues
175* less than equal to SIGMA.
176*
177* N (input) INTEGER
178* The order of the tridiagonal matrix T. N >= 1.
179*
180* D (input) DOUBLE PRECISION array, dimension (2*N - 1)
181* Contains the diagonals and the squares of the off-diagonal
182* elements of the tridiagonal matrix T. These elements are
183* assumed to be interleaved in memory for better cache
184* performance. The diagonal entries of T are in the entries
185* D(1),D(3),...,D(2*N-1), while the squares of the off-diagonal
186* entries are D(2),D(4),...,D(2*N-2). To avoid overflow, the
187* matrix must be scaled so that its largest entry is no greater
188* than overflow**(1/2) * underflow**(1/4) in absolute value,
189* and for greatest accuracy, it should not be much smaller
190* than that.
191*
192* COUNT (output) INTEGER
193* The count of the number of eigenvalues of T less than or
194* equal to SIGMA.
195*
196* =====================================================================
197*
198* .. Local Scalars ..
199*/
200 double lsigma, tmp, *pd, *pe2;
201 Int i;
202/* ..
203* .. Executable Statements ..
204*/
205
206 lsigma = *sigma;
207 pd = d; pe2 = d+1;
208 tmp = *pd - lsigma; pd += 2;
209 *count = (*(((Int *)&tmp)+1) >> 31) & 1;
210 for(i = 1;i < *n;i++){
211 tmp = *pd - *pe2/tmp - lsigma;
212 pd += 2; pe2 += 2;
213 *count += (*(((Int *)&tmp)+1) >> 31) & 1;
214 }
215}
216
217void pdlachkieee_( Int *isieee, double *rmax, double *rmin )
218{
219/*
220*
221* Purpose
222* =======
223*
224* pdlachkieee performs a simple check to make sure that the features
225* of the IEEE standard that we rely on are implemented. In some
226* implementations, pdlachkieee may not return.
227*
228* Note that all arguments are call-by-reference so that this routine
229* can be directly called from Fortran code.
230*
231* This is a ScaLAPACK internal subroutine and arguments are not
232* checked for unreasonable values.
233*
234* Arguments
235* =========
236*
237* ISIEEE (local output) INTEGER
238* On exit, ISIEEE = 1 implies that all the features of the
239* IEEE standard that we rely on are implemented.
240* On exit, ISIEEE = 0 implies that some the features of the
241* IEEE standard that we rely on are missing.
242*
243* RMAX (local input) DOUBLE PRECISION
244* The overflow threshold ( = DLAMCH('O') ).
245*
246* RMIN (local input) DOUBLE PRECISION
247* The underflow threshold ( = DLAMCH('U') ).
248*
249* =====================================================================
250*
251* .. Local Scalars ..
252*/
253 double x, pinf, pzero, ninf, nzero;
254 Int ieflag, *ix, sbit1, sbit2, negone=-1, errornum;
255/* ..
256* .. Executable Statements ..
257*/
258
259 pdlasnbt_( &ieflag );
260
261 pinf = *rmax / *rmin;
262 pzero = 1.0 / pinf;
263 pinf = 1.0 / pzero;
264
265 if( pzero != 0.0 ){
266 printf("pzero = %g should be zero\n",pzero);
267 *isieee = 0;
268 return ;
269 }
270 if( ieflag == 1 ){
271 sbit1 = (*((Int *)&pzero) >> 31) & 1;
272 sbit2 = (*((Int *)&pinf) >> 31) & 1;
273 }else if(ieflag == 2){
274 sbit1 = (*(((Int *)&pzero)+1) >> 31) & 1;
275 sbit2 = (*(((Int *)&pinf)+1) >> 31) & 1;
276 }
277 if( sbit1 == 1 ){
278 printf("Sign of positive infinity is incorrect\n");
279 *isieee = 0;
280 }
281 if( sbit2 == 1 ){
282 printf("Sign of positive zero is incorrect\n");
283 *isieee = 0;
284 }
285
286 ninf = -pinf;
287 nzero = 1.0 / ninf;
288 ninf = 1.0 / nzero;
289
290 if( nzero != 0.0 ){
291 printf("nzero = %g should be zero\n",nzero);
292 *isieee = 0;
293 }
294 if( ieflag == 1 ){
295 sbit1 = (*((Int *)&nzero) >> 31) & 1;
296 sbit2 = (*((Int *)&ninf) >> 31) & 1;
297 }else if(ieflag == 2){
298 sbit1 = (*(((Int *)&nzero)+1) >> 31) & 1;
299 sbit2 = (*(((Int *)&ninf)+1) >> 31) & 1;
300 }
301 if( sbit1 == 0 ){
302 printf("Sign of negative infinity is incorrect\n");
303 *isieee = 0;
304 }
305 if( sbit2 == 0 ){
306 printf("Sign of negative zero is incorrect\n");
307 *isieee = 0;
308 }
309}
#define Int
Definition Bconfig.h:22
void pdlaiectl_(double *sigma, Int *n, double *d, Int *count)
Definition pdlaiect.c:151
void pdlasnbt_(Int *ieflag)
Definition pdlaiect.c:23
void pdlachkieee_(Int *isieee, double *rmax, double *rmin)
Definition pdlaiect.c:217
void pdlaiectb_(double *sigma, Int *n, double *d, Int *count)
Definition pdlaiect.c:85