1 /* ========================================================================== */
2 /* === Core/cholmod_common ================================================== */
3 /* ========================================================================== */
4
5 /* -----------------------------------------------------------------------------
6 * CHOLMOD/Core Module. Copyright (C) 2005-2006,
7 * Univ. of Florida. Author: Timothy A. Davis
8 * -------------------------------------------------------------------------- */
9
10 /* Core utility routines for the cholmod_common object:
11 *
12 * Primary routines:
13 * -----------------
14 * cholmod_start the first call to CHOLMOD
15 * cholmod_finish the last call to CHOLMOD
16 *
17 * Secondary routines:
18 * -------------------
19 * cholmod_defaults restore (most) default control parameters
20 * cholmod_allocate_work allocate (or reallocate) workspace in Common
21 * cholmod_free_work free workspace in Common
22 * cholmod_clear_flag clear Common->Flag in workspace
23 * cholmod_maxrank column dimension of Common->Xwork workspace
24 *
25 * The Common object is unique. It cannot be allocated or deallocated by
26 * CHOLMOD, since it contains the definition of the memory management routines
27 * used (pointers to malloc, free, realloc, and calloc, or their equivalent).
28 * The Common object contains workspace that is used between calls to
29 * CHOLMOD routines. This workspace allocated by CHOLMOD as needed, by
30 * cholmod_allocate_work and cholmod_free_work.
31 */
32
33 #include "cholmod_internal.h"
34 #include "cholmod_core.h"
35
36 #ifdef GPU_BLAS
37 #include "cholmod_gpu.h"
38 #endif
39
40 /* ========================================================================== */
41 /* === cholmod_start ======================================================== */
42 /* ========================================================================== */
43
44 /* Initialize Common default parameters and statistics. Sets workspace
45 * pointers to NULL.
46 *
47 * This routine must be called just once, prior to calling any other CHOLMOD
48 * routine. Do not call this routine after any other CHOLMOD routine (except
49 * cholmod_finish, to start a new CHOLMOD session), or a memory leak will
50 * occur.
51 *
52 * workspace: none
53 */
54
CHOLMOD(start)55 int CHOLMOD(start)
56 (
57 cholmod_common *Common
58 )
59 {
60 int k ;
61
62 if (Common == NULL)
63 {
64 return (FALSE) ;
65 }
66
67 /* ---------------------------------------------------------------------- */
68 /* user error handling routine */
69 /* ---------------------------------------------------------------------- */
70
71 Common->error_handler = NULL ;
72
73 /* ---------------------------------------------------------------------- */
74 /* integer and numerical types */
75 /* ---------------------------------------------------------------------- */
76
77 Common->itype = ITYPE ;
78 Common->dtype = DTYPE ;
79
80 /* ---------------------------------------------------------------------- */
81 /* default control parameters */
82 /* ---------------------------------------------------------------------- */
83
84 CHOLMOD(defaults) (Common) ;
85 Common->try_catch = FALSE ;
86
87 /* ---------------------------------------------------------------------- */
88 /* memory management routines */
89 /* ---------------------------------------------------------------------- */
90
91 /* moved to SuiteSparse_config */
92
93 /* ---------------------------------------------------------------------- */
94 /* complex arithmetic routines */
95 /* ---------------------------------------------------------------------- */
96
97 /* moved to SuiteSparse_config */
98
99 /* ---------------------------------------------------------------------- */
100 /* print routine */
101 /* ---------------------------------------------------------------------- */
102
103 /* moved to SuiteSparse_config */
104
105 /* ---------------------------------------------------------------------- */
106 /* workspace */
107 /* ---------------------------------------------------------------------- */
108
109 /* This code assumes the workspace held in Common is not initialized. If
110 * it is, then a memory leak will occur because the pointers are
111 * overwritten with NULL. */
112
113 Common->nrow = 0 ;
114 Common->mark = EMPTY ;
115 Common->xworksize = 0 ;
116 Common->iworksize = 0 ;
117 Common->Flag = NULL ;
118 Common->Head = NULL ;
119 Common->Iwork = NULL ;
120 Common->Xwork = NULL ;
121 Common->no_workspace_reallocate = FALSE ;
122
123 /* ---------------------------------------------------------------------- */
124 /* statistics */
125 /* ---------------------------------------------------------------------- */
126
127 /* fl and lnz are computed in cholmod_analyze and cholmod_rowcolcounts */
128 Common->fl = EMPTY ;
129 Common->lnz = EMPTY ;
130
131 /* modfl is computed in cholmod_updown, cholmod_rowadd, and cholmod_rowdel*/
132 Common->modfl = EMPTY ;
133
134 /* all routines use status as their error-report code */
135 Common->status = CHOLMOD_OK ;
136
137 Common->malloc_count = 0 ; /* # calls to malloc minus # calls to free */
138 Common->memory_usage = 0 ; /* peak memory usage (in bytes) */
139 Common->memory_inuse = 0 ; /* current memory in use (in bytes) */
140
141 Common->nrealloc_col = 0 ;
142 Common->nrealloc_factor = 0 ;
143 Common->ndbounds_hit = 0 ;
144 Common->rowfacfl = 0 ;
145 Common->aatfl = EMPTY ;
146
147 /* Common->called_nd is TRUE if cholmod_analyze called or NESDIS */
148 Common->called_nd = FALSE ;
149
150 Common->blas_ok = TRUE ; /* false if BLAS int overflow occurs */
151
152 /* ---------------------------------------------------------------------- */
153 /* default SuiteSparseQR knobs and statististics */
154 /* ---------------------------------------------------------------------- */
155
156 for (k = 0 ; k < 10 ; k++) Common->SPQR_istat [k] = 0 ;
157
158 Common->SPQR_flopcount_bound = 0 ; /* upper bound on flop count */
159 Common->SPQR_tol_used = 0 ; /* tolerance used */
160 Common->SPQR_norm_E_fro = 0 ; /* Frobenius norm of dropped entries */
161
162 Common->SPQR_grain = 1 ; /* no Intel TBB multitasking, by default */
163 Common->SPQR_small = 1e6 ; /* target min task size for TBB */
164 Common->SPQR_shrink = 1 ; /* controls SPQR shrink realloc */
165 Common->SPQR_nthreads = 0 ; /* 0: let TBB decide how many threads to use */
166
167 Common->SPQR_flopcount = 0 ; /* flop count for SPQR */
168 Common->SPQR_analyze_time = 0 ; /* analysis time for SPQR */
169 Common->SPQR_factorize_time = 0 ; /* factorize time for SPQR */
170 Common->SPQR_solve_time = 0 ; /* backsolve time for SPQR */
171
172 /* ---------------------------------------------------------------------- */
173 /* GPU initializations */
174 /* ---------------------------------------------------------------------- */
175
176 /* these are destroyed by cholmod_gpu_deallocate and cholmod_gpu_end */
177 Common->cublasHandle = NULL ;
178 Common->cublasEventPotrf [0] = NULL ;
179 Common->cublasEventPotrf [1] = NULL ;
180 Common->cublasEventPotrf [2] = NULL ;
181 for (k = 0 ; k < CHOLMOD_HOST_SUPERNODE_BUFFERS ; k++)
182 {
183 Common->gpuStream [k] = NULL ;
184 Common->updateCBuffersFree [k] = NULL ;
185 }
186 Common->updateCKernelsComplete = NULL;
187
188 /* these are destroyed by cholmod_gpu_deallocate */
189 Common->dev_mempool = NULL;
190 Common->dev_mempool_size = 0;
191 Common->host_pinned_mempool = NULL;
192 Common->host_pinned_mempool_size = 0;
193
194 Common->syrkStart = 0 ;
195
196 Common->cholmod_cpu_gemm_time = 0 ;
197 Common->cholmod_cpu_syrk_time = 0 ;
198 Common->cholmod_cpu_trsm_time = 0 ;
199 Common->cholmod_cpu_potrf_time = 0 ;
200 Common->cholmod_gpu_gemm_time = 0 ;
201 Common->cholmod_gpu_syrk_time = 0 ;
202 Common->cholmod_gpu_trsm_time = 0 ;
203 Common->cholmod_gpu_potrf_time = 0 ;
204 Common->cholmod_assemble_time = 0 ;
205 Common->cholmod_assemble_time2 = 0 ;
206
207 Common->cholmod_cpu_gemm_calls = 0 ;
208 Common->cholmod_cpu_syrk_calls = 0 ;
209 Common->cholmod_cpu_trsm_calls = 0 ;
210 Common->cholmod_cpu_potrf_calls = 0 ;
211
212 Common->cholmod_gpu_gemm_calls = 0 ;
213 Common->cholmod_gpu_syrk_calls = 0 ;
214 Common->cholmod_gpu_trsm_calls = 0 ;
215 Common->cholmod_gpu_potrf_calls = 0 ;
216
217 Common->maxGpuMemBytes = 0;
218 Common->maxGpuMemFraction = 0.0;
219
220 /* SPQR statistics and settings */
221 Common->gpuMemorySize = 1 ; /* default: no GPU memory available */
222 Common->gpuKernelTime = 0.0 ;
223 Common->gpuFlops = 0 ;
224 Common->gpuNumKernelLaunches = 0 ;
225
226 DEBUG_INIT ("cholmod start", Common) ;
227
228 return (TRUE) ;
229 }
230
231
232 /* ========================================================================== */
233 /* === cholmod_defaults ===================================================== */
234 /* ========================================================================== */
235
236 /* Set Common default parameters, except for the function pointers.
237 *
238 * workspace: none
239 */
240
CHOLMOD(defaults)241 int CHOLMOD(defaults)
242 (
243 cholmod_common *Common
244 )
245 {
246 Int i ;
247
248 RETURN_IF_NULL_COMMON (FALSE) ;
249
250 /* ---------------------------------------------------------------------- */
251 /* default control parameters */
252 /* ---------------------------------------------------------------------- */
253
254 Common->dbound = 0.0 ;
255 Common->grow0 = 1.2 ;
256 Common->grow1 = 1.2 ;
257 Common->grow2 = 5 ;
258 Common->maxrank = 8 ;
259
260 Common->final_asis = TRUE ;
261 Common->final_super = TRUE ;
262 Common->final_ll = FALSE ;
263 Common->final_pack = TRUE ;
264 Common->final_monotonic = TRUE ;
265 Common->final_resymbol = FALSE ;
266
267 /* use simplicial factorization if flop/nnz(L) < 40, supernodal otherwise */
268 Common->supernodal = CHOLMOD_AUTO ;
269 Common->supernodal_switch = 40 ;
270
271 Common->nrelax [0] = 4 ;
272 Common->nrelax [1] = 16 ;
273 Common->nrelax [2] = 48 ;
274 Common->zrelax [0] = 0.8 ;
275 Common->zrelax [1] = 0.1 ;
276 Common->zrelax [2] = 0.05 ;
277
278 Common->prefer_zomplex = FALSE ;
279 Common->prefer_upper = TRUE ;
280 Common->prefer_binary = FALSE ;
281 Common->quick_return_if_not_posdef = FALSE ;
282
283 /* METIS workarounds */
284 Common->metis_memory = 0.0 ; /* > 0 for memory guard (2 is reasonable) */
285 Common->metis_nswitch = 3000 ;
286 Common->metis_dswitch = 0.66 ;
287
288 Common->print = 3 ;
289 Common->precise = FALSE ;
290
291 /* ---------------------------------------------------------------------- */
292 /* default ordering methods */
293 /* ---------------------------------------------------------------------- */
294
295 /* Note that if the Partition module is not installed, the CHOLMOD_METIS
296 * and CHOLMOD_NESDIS methods will not be available. cholmod_analyze will
297 * report the CHOLMOD_NOT_INSTALLED error, and safely skip over them.
298 */
299
300 #if (CHOLMOD_MAXMETHODS < 9)
301 #error "CHOLMOD_MAXMETHODS must be 9 or more (defined in cholmod_core.h)."
302 #endif
303
304 /* default strategy: try given, AMD, and then METIS if AMD reports high
305 * fill-in. NESDIS can be used instead, if Common->default_nesdis is TRUE.
306 */
307 Common->nmethods = 0 ; /* use default strategy */
308 Common->default_nesdis = FALSE ; /* use METIS in default strategy */
309
310 Common->current = 0 ; /* current method being tried */
311 Common->selected = 0 ; /* the best method selected */
312
313 /* first, fill each method with default parameters */
314 for (i = 0 ; i <= CHOLMOD_MAXMETHODS ; i++)
315 {
316 /* CHOLMOD's default method is AMD for A or AA' */
317 Common->method [i].ordering = CHOLMOD_AMD ;
318
319 /* CHOLMOD nested dissection and minimum degree parameter */
320 Common->method [i].prune_dense = 10.0 ; /* dense row/col control */
321
322 /* min degree parameters (AMD, COLAMD, SYMAMD, CAMD, CCOLAMD, CSYMAMD)*/
323 Common->method [i].prune_dense2 = -1 ; /* COLAMD dense row control */
324 Common->method [i].aggressive = TRUE ; /* aggressive absorption */
325 Common->method [i].order_for_lu = FALSE ;/* order for Cholesky not LU */
326
327 /* CHOLMOD's nested dissection (METIS + constrained AMD) */
328 Common->method [i].nd_small = 200 ; /* small graphs aren't cut */
329 Common->method [i].nd_compress = TRUE ; /* compress graph & subgraphs */
330 Common->method [i].nd_camd = 1 ; /* use CAMD */
331 Common->method [i].nd_components = FALSE ; /* lump connected comp. */
332 Common->method [i].nd_oksep = 1.0 ; /* sep ok if < oksep*n */
333
334 /* statistics for each method are not yet computed */
335 Common->method [i].fl = EMPTY ;
336 Common->method [i].lnz = EMPTY ;
337 }
338
339 Common->postorder = TRUE ; /* follow ordering with weighted postorder */
340
341 /* Next, define some methods. The first five use default parameters. */
342 Common->method [0].ordering = CHOLMOD_GIVEN ; /* skip if UserPerm NULL */
343 Common->method [1].ordering = CHOLMOD_AMD ;
344 Common->method [2].ordering = CHOLMOD_METIS ;
345 Common->method [3].ordering = CHOLMOD_NESDIS ;
346 Common->method [4].ordering = CHOLMOD_NATURAL ;
347
348 /* CHOLMOD's nested dissection with large leaves of separator tree */
349 Common->method [5].ordering = CHOLMOD_NESDIS ;
350 Common->method [5].nd_small = 20000 ;
351
352 /* CHOLMOD's nested dissection with tiny leaves, and no AMD ordering */
353 Common->method [6].ordering = CHOLMOD_NESDIS ;
354 Common->method [6].nd_small = 4 ;
355 Common->method [6].nd_camd = 0 ; /* no CSYMAMD or CAMD */
356
357 /* CHOLMOD's nested dissection with no dense node removal */
358 Common->method [7].ordering = CHOLMOD_NESDIS ;
359 Common->method [7].prune_dense = -1. ;
360
361 /* COLAMD for A*A', AMD for A */
362 Common->method [8].ordering = CHOLMOD_COLAMD ;
363
364 /* ---------------------------------------------------------------------- */
365 /* GPU configuration and statistics */
366 /* ---------------------------------------------------------------------- */
367
368 #ifdef DLONG
369 Common->useGPU = EMPTY ;
370 #else
371 /* GPU acceleration is not supported for int version of CHOLMOD */
372 Common->useGPU = 0 ;
373 #endif
374
375 return (TRUE) ;
376 }
377
378
379 /* ========================================================================== */
380 /* === cholmod_finish ======================================================= */
381 /* ========================================================================== */
382
383 /* The last call to CHOLMOD must be cholmod_finish. You may call this routine
384 * more than once, and can safely call any other CHOLMOD routine after calling
385 * it (including cholmod_start).
386 *
387 * The statistics and parameter settings in Common are preserved. The
388 * workspace in Common is freed. This routine is just another name for
389 * cholmod_free_work.
390 */
391
CHOLMOD(finish)392 int CHOLMOD(finish)
393 (
394 cholmod_common *Common
395 )
396 {
397 return (CHOLMOD(free_work) (Common)) ;
398 }
399
400
401 /* ========================================================================== */
402 /* === cholmod_allocate_work ================================================ */
403 /* ========================================================================== */
404
405 /* Allocate and initialize workspace for CHOLMOD routines, or increase the size
406 * of already-allocated workspace. If enough workspace is already allocated,
407 * then nothing happens.
408 *
409 * workspace: Flag (nrow), Head (nrow+1), Iwork (iworksize), Xwork (xworksize)
410 */
411
CHOLMOD(allocate_work)412 int CHOLMOD(allocate_work)
413 (
414 /* ---- input ---- */
415 size_t nrow, /* # of rows in the matrix A */
416 size_t iworksize, /* size of Iwork */
417 size_t xworksize, /* size of Xwork */
418 /* --------------- */
419 cholmod_common *Common
420 )
421 {
422 double *W ;
423 Int *Head ;
424 Int i ;
425 size_t nrow1 ;
426 int ok = TRUE ;
427
428 /* ---------------------------------------------------------------------- */
429 /* get inputs */
430 /* ---------------------------------------------------------------------- */
431
432 RETURN_IF_NULL_COMMON (FALSE) ;
433 Common->status = CHOLMOD_OK ;
434
435 /* ---------------------------------------------------------------------- */
436 /* Allocate Flag (nrow) and Head (nrow+1) */
437 /* ---------------------------------------------------------------------- */
438
439 nrow = MAX (1, nrow) ;
440
441 /* nrow1 = nrow + 1 */
442 nrow1 = CHOLMOD(add_size_t) (nrow, 1, &ok) ;
443 if (!ok)
444 {
445 /* nrow+1 causes size_t overflow ; problem is too large */
446 Common->status = CHOLMOD_TOO_LARGE ;
447 CHOLMOD(free_work) (Common) ;
448 return (FALSE) ;
449 }
450
451 if (nrow > Common->nrow)
452 {
453
454 if (Common->no_workspace_reallocate)
455 {
456 /* CHOLMOD is not allowed to change the workspace here */
457 Common->status = CHOLMOD_INVALID ;
458 return (FALSE) ;
459 }
460
461 /* free the old workspace (if any) and allocate new space */
462 Common->Flag = CHOLMOD(free) (Common->nrow, sizeof (Int), Common->Flag,
463 Common) ;
464 Common->Head = CHOLMOD(free) (Common->nrow+1,sizeof (Int), Common->Head,
465 Common) ;
466 Common->Flag = CHOLMOD(malloc) (nrow, sizeof (Int), Common) ;
467 Common->Head = CHOLMOD(malloc) (nrow1, sizeof (Int), Common) ;
468
469 /* record the new size of Flag and Head */
470 Common->nrow = nrow ;
471
472 if (Common->status < CHOLMOD_OK)
473 {
474 CHOLMOD(free_work) (Common) ;
475 return (FALSE) ;
476 }
477
478 /* initialize Flag and Head */
479 Common->mark = EMPTY ;
480 CHOLMOD(clear_flag) (Common) ;
481 Head = Common->Head ;
482 for (i = 0 ; i <= (Int) (nrow) ; i++)
483 {
484 Head [i] = EMPTY ;
485 }
486 }
487
488 /* ---------------------------------------------------------------------- */
489 /* Allocate Iwork (iworksize) */
490 /* ---------------------------------------------------------------------- */
491
492 iworksize = MAX (1, iworksize) ;
493 if (iworksize > Common->iworksize)
494 {
495
496 if (Common->no_workspace_reallocate)
497 {
498 /* CHOLMOD is not allowed to change the workspace here */
499 Common->status = CHOLMOD_INVALID ;
500 return (FALSE) ;
501 }
502
503 /* free the old workspace (if any) and allocate new space.
504 * integer overflow safely detected in cholmod_malloc */
505 CHOLMOD(free) (Common->iworksize, sizeof (Int), Common->Iwork, Common) ;
506 Common->Iwork = CHOLMOD(malloc) (iworksize, sizeof (Int), Common) ;
507
508 /* record the new size of Iwork */
509 Common->iworksize = iworksize ;
510
511 if (Common->status < CHOLMOD_OK)
512 {
513 CHOLMOD(free_work) (Common) ;
514 return (FALSE) ;
515 }
516
517 /* note that Iwork does not need to be initialized */
518 }
519
520 /* ---------------------------------------------------------------------- */
521 /* Allocate Xwork (xworksize) and set it to ((double) 0.) */
522 /* ---------------------------------------------------------------------- */
523
524 /* make sure xworksize is >= 1 */
525 xworksize = MAX (1, xworksize) ;
526 if (xworksize > Common->xworksize)
527 {
528
529 if (Common->no_workspace_reallocate)
530 {
531 /* CHOLMOD is not allowed to change the workspace here */
532 Common->status = CHOLMOD_INVALID ;
533 return (FALSE) ;
534 }
535
536 /* free the old workspace (if any) and allocate new space */
537 CHOLMOD(free) (Common->xworksize, sizeof (double), Common->Xwork,
538 Common) ;
539 Common->Xwork = CHOLMOD(malloc) (xworksize, sizeof (double), Common) ;
540
541 /* record the new size of Xwork */
542 Common->xworksize = xworksize ;
543
544 if (Common->status < CHOLMOD_OK)
545 {
546 CHOLMOD(free_work) (Common) ;
547 return (FALSE) ;
548 }
549
550 /* initialize Xwork */
551 W = Common->Xwork ;
552 for (i = 0 ; i < (Int) xworksize ; i++)
553 {
554 W [i] = 0. ;
555 }
556 }
557
558 return (TRUE) ;
559 }
560
561
562 /* ========================================================================== */
563 /* === cholmod_free_work ==================================================== */
564 /* ========================================================================== */
565
566 /* Deallocate the CHOLMOD workspace.
567 *
568 * workspace: deallocates all workspace in Common
569 */
570
CHOLMOD(free_work)571 int CHOLMOD(free_work)
572 (
573 cholmod_common *Common
574 )
575 {
576 RETURN_IF_NULL_COMMON (FALSE) ;
577 Common->Flag = CHOLMOD(free) (Common->nrow, sizeof (Int),
578 Common->Flag, Common) ;
579 Common->Head = CHOLMOD(free) (Common->nrow+1, sizeof (Int),
580 Common->Head, Common) ;
581 Common->Iwork = CHOLMOD(free) (Common->iworksize, sizeof (Int),
582 Common->Iwork, Common) ;
583 Common->Xwork = CHOLMOD(free) (Common->xworksize, sizeof (double),
584 Common->Xwork, Common) ;
585 Common->nrow = 0 ;
586 Common->iworksize = 0 ;
587 Common->xworksize = 0 ;
588
589 #ifdef GPU_BLAS
590 CHOLMOD(gpu_deallocate) (Common) ;
591 #endif
592 return (TRUE) ;
593 }
594
595
596 /* ========================================================================== */
597 /* === cholmod_clear_flag =================================================== */
598 /* ========================================================================== */
599
600 /* Increment mark to ensure Flag [0..nrow-1] < mark. If integer overflow
601 * occurs, or mark was initially negative, reset the entire array. This is
602 * not an error condition, but an intended function of the Flag workspace.
603 *
604 * workspace: Flag (nrow). Does not modify Flag if nrow is zero.
605 */
606
CHOLMOD(clear_flag)607 SuiteSparse_long CHOLMOD(clear_flag)
608 (
609 cholmod_common *Common
610 )
611 {
612 Int i, nrow, *Flag ;
613
614 RETURN_IF_NULL_COMMON (-1) ;
615
616 Common->mark++ ;
617 if (Common->mark <= 0)
618 {
619 nrow = Common->nrow ;
620 Flag = Common->Flag ;
621 PRINT2 (("reset Flag: nrow "ID"\n", nrow)) ;
622 PRINT2 (("reset Flag: mark %ld\n", Common->mark)) ;
623 for (i = 0 ; i < nrow ; i++)
624 {
625 Flag [i] = EMPTY ;
626 }
627 Common->mark = 0 ;
628 }
629 return (Common->mark) ;
630 }
631
632
633 /* ========================================================================== */
634 /* ==== cholmod_maxrank ===================================================== */
635 /* ========================================================================== */
636
637 /* Find a valid value of Common->maxrank. Returns 0 if error, or 2, 4, or 8
638 * if successful. */
639
CHOLMOD(maxrank)640 size_t CHOLMOD(maxrank) /* returns validated value of Common->maxrank */
641 (
642 /* ---- input ---- */
643 size_t n, /* A and L will have n rows */
644 /* --------------- */
645 cholmod_common *Common
646 )
647 {
648 size_t maxrank ;
649 RETURN_IF_NULL_COMMON (0) ;
650 maxrank = Common->maxrank ;
651 if (n > 0)
652 {
653 /* Ensure maxrank*n*sizeof(double) does not result in integer overflow.
654 * If n is so large that 2*n*sizeof(double) results in integer overflow
655 * (n = 268,435,455 if an Int is 32 bits), then maxrank will be 0 or 1,
656 * but maxrank will be set to 2 below. 2*n will not result in integer
657 * overflow, and CHOLMOD will run out of memory or safely detect integer
658 * overflow elsewhere.
659 */
660 maxrank = MIN (maxrank, Size_max / (n * sizeof (double))) ;
661 }
662 if (maxrank <= 2)
663 {
664 maxrank = 2 ;
665 }
666 else if (maxrank <= 4)
667 {
668 maxrank = 4 ;
669 }
670 else
671 {
672 maxrank = 8 ;
673 }
674 return (maxrank) ;
675 }
676
677
678 /* ========================================================================== */
679 /* === cholmod_dbound ======================================================= */
680 /* ========================================================================== */
681
682 /* Ensure the absolute value of a diagonal entry, D (j,j), is greater than
683 * Common->dbound. This routine is not meant for the user to call. It is used
684 * by the various LDL' factorization and update/downdate routines. The
685 * default value of Common->dbound is zero, and in that case this routine is not
686 * called at all. No change is made if D (j,j) is NaN. CHOLMOD does not call
687 * this routine if Common->dbound is NaN.
688 */
689
CHOLMOD(dbound)690 double CHOLMOD(dbound) /* returns modified diagonal entry of D */
691 (
692 /* ---- input ---- */
693 double dj, /* diagonal entry of D, for LDL' factorization */
694 /* --------------- */
695 cholmod_common *Common
696 )
697 {
698 double dbound ;
699 RETURN_IF_NULL_COMMON (0) ;
700 if (!IS_NAN (dj))
701 {
702 dbound = Common->dbound ;
703 if (dj < 0)
704 {
705 if (dj > -dbound)
706 {
707 dj = -dbound ;
708 Common->ndbounds_hit++ ;
709 if (Common->status == CHOLMOD_OK)
710 {
711 ERROR (CHOLMOD_DSMALL, "diagonal below threshold") ;
712 }
713 }
714 }
715 else
716 {
717 if (dj < dbound)
718 {
719 dj = dbound ;
720 Common->ndbounds_hit++ ;
721 if (Common->status == CHOLMOD_OK)
722 {
723 ERROR (CHOLMOD_DSMALL, "diagonal below threshold") ;
724 }
725 }
726 }
727 }
728 return (dj) ;
729 }
730
731
732 /* ========================================================================== */
733 /* === scorecomp ============================================================ */
734 /* ========================================================================== */
735
736 /* For sorting descendant supernodes with qsort */
CHOLMOD(score_comp)737 int CHOLMOD(score_comp) (struct cholmod_descendant_score_t *i,
738 struct cholmod_descendant_score_t *j)
739 {
740 if ((*i).score < (*j).score)
741 {
742 return (1) ;
743 }
744 else
745 {
746 return (-1) ;
747 }
748 }
749