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