Amesos Package Browser (Single Doxygen Collection)  Development
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
amesos_cholmod_complex.c
Go to the documentation of this file.
1 /* ========================================================================== */
2 /* === Core/cholmod_complex ================================================= */
3 /* ========================================================================== */
4 
5 /* -----------------------------------------------------------------------------
6  * CHOLMOD/Core Module. Copyright (C) 2005-2006,
7  * Univ. of Florida. Author: Timothy A. Davis
8  * The CHOLMOD/Core Module is licensed under Version 2.1 of the GNU
9  * Lesser General Public License. See lesser.txt for a text of the license.
10  * CHOLMOD is also available under other licenses; contact authors for details.
11  * http://www.cise.ufl.edu/research/sparse
12  * -------------------------------------------------------------------------- */
13 
14 /* If you convert a matrix that contains uninitialized data, valgrind will
15  * complain. This can occur in a factor L which has gaps (a partial
16  * factorization, or after updates that change the nonzero pattern), an
17  * unpacked sparse matrix, a dense matrix with leading dimension d > # of rows,
18  * or any matrix (dense, sparse, triplet, or factor) with more space allocated
19  * than is used. You can safely ignore any of these complaints by valgrind. */
20 
22 #include "amesos_cholmod_core.h"
23 
24 /* ========================================================================== */
25 /* === cholmod_hypot ======================================================== */
26 /* ========================================================================== */
27 
28 /* There is an equivalent routine called hypot in <math.h>, which conforms
29  * to ANSI C99. However, CHOLMOD does not assume that ANSI C99 is available.
30  * You can use the ANSI C99 hypot routine with:
31  *
32  * #include <math.h>
33  * Common->hypotenuse = hypot ;
34  *
35  * Default value of the Common->hypotenuse pointer is cholmod_hypot.
36  *
37  * s = hypot (x,y) computes s = sqrt (x*x + y*y) but does so more accurately.
38  * The NaN cases for the double relops x >= y and x+y == x are safely ignored.
39  */
40 
41 double CHOLMOD(hypot) (double x, double y)
42 {
43  double s, r ;
44  x = fabs (x) ;
45  y = fabs (y) ;
46  if (x >= y)
47  {
48  if (x + y == x)
49  {
50  s = x ;
51  }
52  else
53  {
54  r = y / x ;
55  s = x * sqrt (1.0 + r*r) ;
56  }
57  }
58  else
59  {
60  if (y + x == y)
61  {
62  s = y ;
63  }
64  else
65  {
66  r = x / y ;
67  s = y * sqrt (1.0 + r*r) ;
68  }
69  }
70  return (s) ;
71 }
72 
73 
74 /* ========================================================================== */
75 /* === cholmod_divcomplex =================================================== */
76 /* ========================================================================== */
77 
78 /* c = a/b where c, a, and b are complex. The real and imaginary parts are
79  * passed as separate arguments to this routine. The NaN case is ignored
80  * for the double relop br >= bi. Returns 1 if the denominator is zero,
81  * 0 otherwise. Note that this return value is the single exception to the
82  * rule that all CHOLMOD routines that return int return TRUE if successful
83  * or FALSE otherise.
84  *
85  * This uses ACM Algo 116, by R. L. Smith, 1962, which tries to avoid
86  * underflow and overflow.
87  *
88  * c can be the same variable as a or b.
89  *
90  * Default value of the Common->complex_divide pointer is cholmod_divcomplex.
91  */
92 
94 (
95  double ar, double ai, /* real and imaginary parts of a */
96  double br, double bi, /* real and imaginary parts of b */
97  double *cr, double *ci /* real and imaginary parts of c */
98 )
99 {
100  double tr, ti, r, den ;
101  if (fabs (br) >= fabs (bi))
102  {
103  r = bi / br ;
104  den = br + r * bi ;
105  tr = (ar + ai * r) / den ;
106  ti = (ai - ar * r) / den ;
107  }
108  else
109  {
110  r = br / bi ;
111  den = r * br + bi ;
112  tr = (ar * r + ai) / den ;
113  ti = (ai * r - ar) / den ;
114  }
115  *cr = tr ;
116  *ci = ti ;
117  return (IS_ZERO (den)) ;
118 }
119 
120 
121 /* ========================================================================== */
122 /* === change_complexity ==================================================== */
123 /* ========================================================================== */
124 
125 /* X and Z represent an array of size nz, with numeric xtype given by xtype_in.
126  *
127  * If xtype_in is:
128  * CHOLMOD_PATTERN: X and Z must be NULL.
129  * CHOLMOD_REAL: X is of size nz, Z must be NULL.
130  * CHOLMOD_COMPLEX: X is of size 2*nz, Z must be NULL.
131  * CHOLMOD_ZOMPLEX: X is of size nz, Z is of size nz.
132  *
133  * The array is changed into the numeric xtype given by xtype_out, with the
134  * same definitions of X and Z above. Note that the input conditions, above,
135  * are not checked. These are checked in the caller routine.
136  *
137  * Returns TRUE if successful, FALSE otherwise. X and Z are not modified if
138  * not successful.
139  */
140 
141 static int change_complexity
142 (
143  /* ---- input ---- */
144  Int nz, /* size of X and/or Z */
145  int xtype_in, /* xtype of X and Z on input */
146  int xtype_out, /* requested xtype of X and Z on output */
147  int xtype1, /* xtype_out must be in the range [xtype1 .. xtype2] */
148  int xtype2,
149  /* ---- in/out --- */
150  void **XX, /* old X on input, new X on output */
151  void **ZZ, /* old Z on input, new Z on output */
152  /* --------------- */
153  cholmod_common *Common
154 )
155 {
156  double *Xold, *Zold, *Xnew, *Znew ;
157  Int k ;
158  size_t nz2 ;
159 
160  if (xtype_out < xtype1 || xtype_out > xtype2)
161  {
162  ERROR (CHOLMOD_INVALID, "invalid xtype") ;
163  return (FALSE) ;
164  }
165 
166  Common->status = CHOLMOD_OK ;
167  Xold = *XX ;
168  Zold = *ZZ ;
169 
170  switch (xtype_in)
171  {
172 
173  /* ------------------------------------------------------------------ */
174  /* converting from pattern */
175  /* ------------------------------------------------------------------ */
176 
177  case CHOLMOD_PATTERN:
178 
179  switch (xtype_out)
180  {
181 
182  /* ---------------------------------------------------------- */
183  /* pattern -> real */
184  /* ---------------------------------------------------------- */
185 
186  case CHOLMOD_REAL:
187  /* allocate X and set to all ones */
188  Xnew = CHOLMOD(malloc) (nz, sizeof (double), Common) ;
189  if (Common->status < CHOLMOD_OK)
190  {
191  return (FALSE) ;
192  }
193  for (k = 0 ; k < nz ; k++)
194  {
195  Xnew [k] = 1 ;
196  }
197  *XX = Xnew ;
198  break ;
199 
200  /* ---------------------------------------------------------- */
201  /* pattern -> complex */
202  /* ---------------------------------------------------------- */
203 
204  case CHOLMOD_COMPLEX:
205  /* allocate X and set to all ones */
206  Xnew = CHOLMOD(malloc) (nz, 2*sizeof (double), Common) ;
207  if (Common->status < CHOLMOD_OK)
208  {
209  return (FALSE) ;
210  }
211  for (k = 0 ; k < nz ; k++)
212  {
213  Xnew [2*k ] = 1 ;
214  Xnew [2*k+1] = 0 ;
215  }
216  *XX = Xnew ;
217  break ;
218 
219  /* ---------------------------------------------------------- */
220  /* pattern -> zomplex */
221  /* ---------------------------------------------------------- */
222 
223  case CHOLMOD_ZOMPLEX:
224  /* allocate X and Z and set to all ones */
225  Xnew = CHOLMOD(malloc) (nz, sizeof (double), Common) ;
226  Znew = CHOLMOD(malloc) (nz, sizeof (double), Common) ;
227  if (Common->status < CHOLMOD_OK)
228  {
229  CHOLMOD(free) (nz, sizeof (double), Xnew, Common) ;
230  CHOLMOD(free) (nz, sizeof (double), Znew, Common) ;
231  return (FALSE) ;
232  }
233  for (k = 0 ; k < nz ; k++)
234  {
235  Xnew [k] = 1 ;
236  Znew [k] = 0 ;
237  }
238  *XX = Xnew ;
239  *ZZ = Znew ;
240  break ;
241  }
242  break ;
243 
244  /* ------------------------------------------------------------------ */
245  /* converting from real */
246  /* ------------------------------------------------------------------ */
247 
248  case CHOLMOD_REAL:
249 
250  switch (xtype_out)
251  {
252 
253  /* ---------------------------------------------------------- */
254  /* real -> pattern */
255  /* ---------------------------------------------------------- */
256 
257  case CHOLMOD_PATTERN:
258  /* free X */
259  *XX = CHOLMOD(free) (nz, sizeof (double), *XX, Common) ;
260  break ;
261 
262  /* ---------------------------------------------------------- */
263  /* real -> complex */
264  /* ---------------------------------------------------------- */
265 
266  case CHOLMOD_COMPLEX:
267  /* allocate a new X and copy the old X */
268  Xnew = CHOLMOD(malloc) (nz, 2*sizeof (double), Common) ;
269  if (Common->status < CHOLMOD_OK)
270  {
271  return (FALSE) ;
272  }
273  for (k = 0 ; k < nz ; k++)
274  {
275  Xnew [2*k ] = Xold [k] ;
276  Xnew [2*k+1] = 0 ;
277  }
278  CHOLMOD(free) (nz, sizeof (double), *XX, Common) ;
279  *XX = Xnew ;
280  break ;
281 
282  /* ---------------------------------------------------------- */
283  /* real -> zomplex */
284  /* ---------------------------------------------------------- */
285 
286  case CHOLMOD_ZOMPLEX:
287  /* allocate a new Z and set it to zero */
288  Znew = CHOLMOD(malloc) (nz, sizeof (double), Common) ;
289  if (Common->status < CHOLMOD_OK)
290  {
291  return (FALSE) ;
292  }
293  for (k = 0 ; k < nz ; k++)
294  {
295  Znew [k] = 0 ;
296  }
297  *ZZ = Znew ;
298  break ;
299  }
300  break ;
301 
302  /* ------------------------------------------------------------------ */
303  /* converting from complex */
304  /* ------------------------------------------------------------------ */
305 
306  case CHOLMOD_COMPLEX:
307 
308  switch (xtype_out)
309  {
310 
311  /* ---------------------------------------------------------- */
312  /* complex -> pattern */
313  /* ---------------------------------------------------------- */
314 
315  case CHOLMOD_PATTERN:
316  /* free X */
317  *XX = CHOLMOD(free) (nz, 2*sizeof (double), *XX, Common) ;
318  break ;
319 
320  /* ---------------------------------------------------------- */
321  /* complex -> real */
322  /* ---------------------------------------------------------- */
323 
324  case CHOLMOD_REAL:
325  /* pack the real part of X, discarding the imaginary part */
326  for (k = 0 ; k < nz ; k++)
327  {
328  Xold [k] = Xold [2*k] ;
329  }
330  /* shrink X in half (this cannot fail) */
331  nz2 = 2*nz ;
332  *XX = CHOLMOD(realloc) (nz, sizeof (double), *XX, &nz2,
333  Common) ;
334  break ;
335 
336  /* ---------------------------------------------------------- */
337  /* complex -> zomplex */
338  /* ---------------------------------------------------------- */
339 
340  case CHOLMOD_ZOMPLEX:
341  /* allocate X and Z and copy the old X into them */
342  Xnew = CHOLMOD(malloc) (nz, sizeof (double), Common) ;
343  Znew = CHOLMOD(malloc) (nz, sizeof (double), Common) ;
344  if (Common->status < CHOLMOD_OK)
345  {
346  CHOLMOD(free) (nz, sizeof (double), Xnew, Common) ;
347  CHOLMOD(free) (nz, sizeof (double), Znew, Common) ;
348  return (FALSE) ;
349  }
350  for (k = 0 ; k < nz ; k++)
351  {
352  Xnew [k] = Xold [2*k ] ;
353  Znew [k] = Xold [2*k+1] ;
354  }
355  CHOLMOD(free) (nz, 2*sizeof (double), *XX, Common) ;
356  *XX = Xnew ;
357  *ZZ = Znew ;
358  break ;
359  }
360  break ;
361 
362  /* ------------------------------------------------------------------ */
363  /* converting from zomplex */
364  /* ------------------------------------------------------------------ */
365 
366  case CHOLMOD_ZOMPLEX:
367 
368  switch (xtype_out)
369  {
370 
371  /* ---------------------------------------------------------- */
372  /* zomplex -> pattern */
373  /* ---------------------------------------------------------- */
374 
375  case CHOLMOD_PATTERN:
376  /* free X and Z */
377  *XX = CHOLMOD(free) (nz, sizeof (double), *XX, Common) ;
378  *ZZ = CHOLMOD(free) (nz, sizeof (double), *ZZ, Common) ;
379  break ;
380 
381  /* ---------------------------------------------------------- */
382  /* zomplex -> real */
383  /* ---------------------------------------------------------- */
384 
385  case CHOLMOD_REAL:
386  /* free the imaginary part */
387  *ZZ = CHOLMOD(free) (nz, sizeof (double), *ZZ, Common) ;
388  break ;
389 
390  /* ---------------------------------------------------------- */
391  /* zomplex -> complex */
392  /* ---------------------------------------------------------- */
393 
394  case CHOLMOD_COMPLEX:
395  Xnew = CHOLMOD(malloc) (nz, 2*sizeof (double), Common) ;
396  if (Common->status < CHOLMOD_OK)
397  {
398  return (FALSE) ;
399  }
400  for (k = 0 ; k < nz ; k++)
401  {
402  Xnew [2*k ] = Xold [k] ;
403  Xnew [2*k+1] = Zold [k] ;
404  }
405  CHOLMOD(free) (nz, sizeof (double), *XX, Common) ;
406  CHOLMOD(free) (nz, sizeof (double), *ZZ, Common) ;
407  *XX = Xnew ;
408  *ZZ = NULL ;
409  break ;
410 
411  }
412  break ;
413  }
414 
415  return (TRUE) ;
416 }
417 
418 
419 /* ========================================================================== */
420 /* === cholmod_sparse_xtype ================================================= */
421 /* ========================================================================== */
422 
423 /* Change the numeric xtype of a sparse matrix. Supports any type on input
424  * and output (pattern, real, complex, or zomplex). */
425 
427 (
428  /* ---- input ---- */
429  int to_xtype, /* requested xtype */
430  /* ---- in/out --- */
431  cholmod_sparse *A, /* sparse matrix to change */
432  /* --------------- */
433  cholmod_common *Common
434 )
435 {
436  Int ok ;
438  RETURN_IF_NULL (A, FALSE) ;
440 
441  ok = change_complexity (A->nzmax, A->xtype, to_xtype,
442  CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, &(A->x), &(A->z), Common) ;
443  if (ok)
444  {
445  A->xtype = to_xtype ;
446  }
447  return (ok) ;
448 }
449 
450 
451 /* ========================================================================== */
452 /* === cholmod_triplet_xtype ================================================ */
453 /* ========================================================================== */
454 
455 /* Change the numeric xtype of a triplet matrix. Supports any type on input
456  * and output (pattern, real, complex, or zomplex). */
457 
459 (
460  /* ---- input ---- */
461  int to_xtype, /* requested xtype */
462  /* ---- in/out --- */
463  cholmod_triplet *T, /* triplet matrix to change */
464  /* --------------- */
465  cholmod_common *Common
466 )
467 {
468  Int ok ;
470  RETURN_IF_NULL (T, FALSE) ;
472  ok = change_complexity (T->nzmax, T->xtype, to_xtype,
473  CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, &(T->x), &(T->z), Common) ;
474  if (ok)
475  {
476  T->xtype = to_xtype ;
477  }
478  return (ok) ;
479 }
480 
481 
482 /* ========================================================================== */
483 /* === cholmod_dense_xtype ================================================= */
484 /* ========================================================================== */
485 
486 /* Change the numeric xtype of a dense matrix. Supports real, complex or
487  * zomplex on input and output */
488 
489 int CHOLMOD(dense_xtype)
490 (
491  /* ---- input ---- */
492  int to_xtype, /* requested xtype */
493  /* ---- in/out --- */
494  cholmod_dense *X, /* dense matrix to change */
495  /* --------------- */
496  cholmod_common *Common
497 )
498 {
499  Int ok ;
501  RETURN_IF_NULL (X, FALSE) ;
503  ok = change_complexity (X->nzmax, X->xtype, to_xtype,
504  CHOLMOD_REAL, CHOLMOD_ZOMPLEX, &(X->x), &(X->z), Common) ;
505  if (ok)
506  {
507  X->xtype = to_xtype ;
508  }
509  return (ok) ;
510 }
511 
512 
513 /* ========================================================================== */
514 /* === cholmod_factor_xtype ================================================= */
515 /* ========================================================================== */
516 
517 /* Change the numeric xtype of a factor. Supports real, complex or zomplex on
518  * input and output. Supernodal zomplex factors are not supported. */
519 
521 (
522  /* ---- input ---- */
523  int to_xtype, /* requested xtype */
524  /* ---- in/out --- */
525  cholmod_factor *L, /* factor to change */
526  /* --------------- */
527  cholmod_common *Common
528 )
529 {
530  Int ok ;
532  RETURN_IF_NULL (L, FALSE) ;
534  if (L->is_super &&
535  (L->xtype == CHOLMOD_ZOMPLEX || to_xtype == CHOLMOD_ZOMPLEX))
536  {
537  ERROR (CHOLMOD_INVALID, "invalid xtype for supernodal L") ;
538  return (FALSE) ;
539  }
540  ok = change_complexity ((L->is_super ? L->xsize : L->nzmax), L->xtype,
541  to_xtype, CHOLMOD_REAL, CHOLMOD_ZOMPLEX, &(L->x), &(L->z), Common) ;
542  if (ok)
543  {
544  L->xtype = to_xtype ;
545  }
546  return (ok) ;
547 }
int CHOLMOD() sparse_xtype(int to_xtype, cholmod_sparse *A, cholmod_common *Common)
#define Int
#define CHOLMOD_COMPLEX
#define FALSE
int CHOLMOD() divcomplex(double ar, double ai, double br, double bi, double *cr, double *ci)
#define RETURN_IF_NULL_COMMON(result)
#define CHOLMOD_PATTERN
int CHOLMOD() dense_xtype(int to_xtype, cholmod_dense *X, cholmod_common *Common)
#define CHOLMOD(name)
static int change_complexity(Int nz, int xtype_in, int xtype_out, int xtype1, int xtype2, void **XX, void **ZZ, cholmod_common *Common)
#define CHOLMOD_REAL
#define NULL
int CHOLMOD() factor_xtype(int to_xtype, cholmod_factor *L, cholmod_common *Common)
#define IS_ZERO(x)
#define CHOLMOD_INVALID
#define CHOLMOD_OK
#define RETURN_IF_NULL(A, result)
double CHOLMOD() hypot(double x, double y)
int CHOLMOD() triplet_xtype(int to_xtype, cholmod_triplet *T, cholmod_common *Common)
#define ERROR(status, msg)
#define TRUE
#define RETURN_IF_XTYPE_INVALID(A, xtype1, xtype2, result)
#define CHOLMOD_ZOMPLEX