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