LCOV - code coverage report
Current view: top level - /builds/ug4-project/ugcore/ug4-new/plugins/SuperLU6/external/superlu/SRC - sp_coletree.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 75 0
Test Date: 2026-06-01 23:54:59 Functions: 0.0 % 5 0

            Line data    Source code
       1              : /*
       2              : Copyright (c) 2003, The Regents of the University of California, through
       3              : Lawrence Berkeley National Laboratory (subject to receipt of any required 
       4              : approvals from U.S. Dept. of Energy) 
       5              : 
       6              : All rights reserved. 
       7              : 
       8              : The source code is distributed under BSD license, see the file License.txt
       9              : at the top-level directory.
      10              : */
      11              : /*
      12              :  * -- SuperLU routine (version 3.1) --
      13              :  * Univ. of California Berkeley, Xerox Palo Alto Research Center,
      14              :  * and Lawrence Berkeley National Lab.
      15              :  * August 1, 2008
      16              :  *
      17              :  * Copyright (c) 1994 by Xerox Corporation.  All rights reserved.
      18              :  *
      19              :  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY
      20              :  * EXPRESSED OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
      21              :  *
      22              :  * Permission is hereby granted to use or copy this program for any
      23              :  * purpose, provided the above notices are retained on all copies.
      24              :  * Permission to modify the code and to distribute modified code is
      25              :  * granted, provided the above notices are retained, and a notice that
      26              :  * the code was modified is included with the above copyright notice.
      27              : */
      28              : /*! \file
      29              :  * \brief Tree layout and computation routines
      30              :  *
      31              :  * \ingroup Common
      32              :  */
      33              : 
      34              : /*  Elimination tree computation and layout routines */
      35              : 
      36              : #include <stdio.h>
      37              : #include <stdlib.h>
      38              : #include "slu_ddefs.h"
      39              : 
      40              : /* 
      41              :  *  Implementation of disjoint set union routines.
      42              :  *  Elements are integers in 0..n-1, and the 
      43              :  *  names of the sets themselves are of type int.
      44              :  *  
      45              :  *  Calls are:
      46              :  *  initialize_disjoint_sets (n) initial call.
      47              :  *  s = make_set (i)             returns a set containing only i.
      48              :  *  s = link (t, u)              returns s = t union u, destroying t and u.
      49              :  *  s = find (i)                 return name of set containing i.
      50              :  *  finalize_disjoint_sets       final call.
      51              :  *
      52              :  *  This implementation uses path compression but not weighted union.
      53              :  *  See Tarjan's book for details.
      54              :  *  John Gilbert, CMI, 1987.
      55              :  *
      56              :  *  Implemented path-halving by XSL 07/05/95.
      57              :  */
      58              : 
      59              : 
      60              : static 
      61            0 : int *mxCallocInt(int n)
      62              : {
      63              :     register int i;
      64              :     int *buf;
      65              : 
      66            0 :     buf = (int *) SUPERLU_MALLOC( n * sizeof(int) );
      67            0 :     if ( !buf ) {
      68            0 :          ABORT("SUPERLU_MALLOC fails for buf in mxCallocInt()");
      69              :        }
      70            0 :     for (i = 0; i < n; i++) buf[i] = 0;
      71            0 :     return (buf);
      72              : }
      73              :       
      74              : static
      75              : void initialize_disjoint_sets (
      76              :                                int n,
      77              :                                int **pp
      78              :                                )
      79              : {
      80            0 :         (*pp) = mxCallocInt(n);
      81              : }
      82              : 
      83              : 
      84              : static
      85              : int make_set (
      86              :               int i,
      87              :               int *pp
      88              :               )
      89              : {
      90            0 :         pp[i] = i;
      91              :         return i;
      92              : }
      93              : 
      94              : 
      95              : static
      96              : int link (
      97              :           int s,
      98              :           int t,
      99              :           int *pp
     100              :           )
     101              : {
     102            0 :         pp[s] = t;
     103              :         return t;
     104              : }
     105              : 
     106              : 
     107              : /* PATH HALVING */
     108              : static
     109              : int find (
     110              :           int i,
     111              :           int *pp
     112              :           )
     113              : {
     114              :     register int p, gp;
     115              :     
     116            0 :     p = pp[i];
     117            0 :     gp = pp[p];
     118            0 :     while (gp != p) {
     119            0 :         pp[i] = gp;
     120              :         i = gp;
     121            0 :         p = pp[i];
     122            0 :         gp = pp[p];
     123              :     }
     124              :     return (p);
     125              : }
     126              : 
     127              : #if 0
     128              : /* PATH COMPRESSION */
     129              : static
     130              : int find (
     131              :         int i
     132              :         )
     133              : {
     134              :         if (pp[i] != i) 
     135              :                 pp[i] = find (pp[i]);
     136              :         return pp[i];
     137              : }
     138              : #endif
     139              : 
     140              : static
     141              : void finalize_disjoint_sets (
     142              :                              int *pp
     143              :                              )
     144              : {
     145            0 :         SUPERLU_FREE(pp);
     146              : }
     147              : 
     148              : 
     149              : /*
     150              :  *      Find the elimination tree for A'*A.
     151              :  *      This uses something similar to Liu's algorithm. 
     152              :  *      It runs in time O(nz(A)*log n) and does not form A'*A.
     153              :  *
     154              :  *      Input:
     155              :  *        Sparse matrix A.  Numeric values are ignored, so any
     156              :  *        explicit zeros are treated as nonzero.
     157              :  *      Output:
     158              :  *        Integer array of parents representing the elimination
     159              :  *        tree of the symbolic product A'*A.  Each vertex is a
     160              :  *        column of A, and nc means a root of the elimination forest.
     161              :  *
     162              :  *      John R. Gilbert, Xerox, 10 Dec 1990
     163              :  *      Based on code by JRG dated 1987, 1988, and 1990.
     164              :  */
     165              : 
     166              : /*
     167              :  * Nonsymmetric elimination tree
     168              :  */
     169            0 : int sp_coletree(
     170              :                 const int_t *acolst, const int_t *acolend, /* column start and end past 1 */
     171              :                 const int_t *arow,                 /* row indices of A */
     172              :                 int nr, int nc,            /* dimension of A */
     173              :                 int *parent)               /* parent in elim tree */
     174              : {
     175              :         int     *root;                  /* root of subtree of etree     */
     176              :         int     *firstcol;              /* first nonzero col in each row*/
     177              :         int     rset, cset;             
     178              :         int     row, col;
     179              :         int     rroot;
     180              :         int     p;
     181              :         int     *pp;
     182              : 
     183            0 :         root = mxCallocInt (nc);
     184              :         initialize_disjoint_sets (nc, &pp);
     185              : 
     186              :         /* Compute firstcol[row] = first nonzero column in row */
     187              : 
     188            0 :         firstcol = mxCallocInt (nr);
     189            0 :         for (row = 0; row < nr; firstcol[row++] = nc);
     190            0 :         for (col = 0; col < nc; col++) 
     191            0 :                 for (p = acolst[col]; p < acolend[col]; p++) {
     192            0 :                         row = arow[p];
     193            0 :                         firstcol[row] = SUPERLU_MIN(firstcol[row], col);
     194              :                 }
     195              : 
     196              :         /* Compute etree by Liu's algorithm for symmetric matrices,
     197              :            except use (firstcol[r],c) in place of an edge (r,c) of A.
     198              :            Thus each row clique in A'*A is replaced by a star
     199              :            centered at its first vertex, which has the same fill. */
     200              : 
     201            0 :         for (col = 0; col < nc; col++) {
     202              :                 cset = make_set (col, pp);
     203            0 :                 root[cset] = col;
     204            0 :                 parent[col] = nc; /* Matlab */
     205            0 :                 for (p = acolst[col]; p < acolend[col]; p++) {
     206            0 :                         row = firstcol[arow[p]];
     207            0 :                         if (row >= col) continue;
     208              :                         rset = find (row, pp);
     209            0 :                         rroot = root[rset];
     210            0 :                         if (rroot != col) {
     211            0 :                                 parent[rroot] = col;
     212              :                                 cset = link (cset, rset, pp);
     213            0 :                                 root[cset] = col;
     214              :                         }
     215              :                 }
     216              :         }
     217              : 
     218            0 :         SUPERLU_FREE (root);
     219            0 :         SUPERLU_FREE (firstcol);
     220              :         finalize_disjoint_sets (pp);
     221            0 :         return 0;
     222              : }
     223              : 
     224              : /*
     225              :  *  q = TreePostorder (n, p);
     226              :  *
     227              :  *      Postorder a tree.
     228              :  *      Input:
     229              :  *        p is a vector of parent pointers for a forest whose
     230              :  *        vertices are the integers 0 to n-1; p[root]==n.
     231              :  *      Output:
     232              :  *        q is a vector indexed by 0..n-1 such that q[i] is the
     233              :  *        i-th vertex in a postorder numbering of the tree.
     234              :  *
     235              :  *        ( 2/7/95 modified by X.Li:
     236              :  *          q is a vector indexed by 0:n-1 such that vertex i is the
     237              :  *          q[i]-th vertex in a postorder numbering of the tree.
     238              :  *          That is, this is the inverse of the previous q. )
     239              :  *
     240              :  *      In the child structure, lower-numbered children are represented
     241              :  *      first, so that a tree which is already numbered in postorder
     242              :  *      will not have its order changed.
     243              :  *    
     244              :  *  Written by John Gilbert, Xerox, 10 Dec 1990.
     245              :  *  Based on code written by John Gilbert at CMI in 1987.
     246              :  */
     247              : 
     248              : #if 0  // replaced by a non-recursive version 
     249              : static
     250              : /*
     251              :  * Depth-first search from vertex v.
     252              :  */
     253              : void etdfs (
     254              :             int   v,
     255              :             int   first_kid[],
     256              :             int   next_kid[],
     257              :             int   post[], 
     258              :             int   *postnum
     259              :             )
     260              : {
     261              :         int     w;
     262              : 
     263              :         for (w = first_kid[v]; w != -1; w = next_kid[w]) {
     264              :                 etdfs (w, first_kid, next_kid, post, postnum);
     265              :         }
     266              :         /* post[postnum++] = v; in Matlab */
     267              :         post[v] = (*postnum)++;    /* Modified by X. Li on 08/10/07 */
     268              : }
     269              : #endif
     270              : 
     271              : static
     272              : /*
     273              :  * Depth-first search from vertex n.  No recursion.
     274              :  * This routine was contributed by Cédric Doucet, CEDRAT Group, Meylan, France.
     275              :  */
     276            0 : void nr_etdfs (int n, const int *parent,
     277              :                const int *first_kid, const int *next_kid,
     278              :                int *post, int postnum)
     279              : {
     280              :     int current = n, first, next;
     281              : 
     282            0 :     while (postnum != n){
     283              :      
     284              :         /* no kid for the current node */
     285            0 :         first = first_kid[current];
     286              : 
     287              :         /* no first kid for the current node */
     288            0 :         if (first == -1){
     289              : 
     290              :             /* numbering this node because it has no kid */
     291            0 :             post[current] = postnum++;
     292              : 
     293              :             /* looking for the next kid */
     294            0 :             next = next_kid[current];
     295              : 
     296            0 :             while (next == -1){
     297              : 
     298              :                 /* no more kids : back to the parent node */
     299            0 :                 current = parent[current];
     300              : 
     301              :                 /* numbering the parent node */
     302            0 :                 post[current] = postnum++;
     303              : 
     304              :                 /* get the next kid */
     305            0 :                 next = next_kid[current];
     306              :             }
     307              :             
     308              :             /* stopping criterion */
     309            0 :             if (postnum==n+1) return;
     310              : 
     311              :             /* updating current node */
     312              :             current = next;
     313              :         }
     314              :         /* updating current node */
     315              :         else {
     316              :             current = first;
     317              :         }
     318              :     }
     319              : }
     320              : 
     321              : /*
     322              :  * Post order a tree
     323              :  */
     324            0 : int *TreePostorder(
     325              :                    int n,
     326              :                    int *parent
     327              :                    )
     328              : {
     329              :         int     *first_kid, *next_kid;  /* Linked list of children.     */
     330              :         int     *post, postnum;
     331              :         int     v, dad;
     332              : 
     333              :         /* Allocate storage for working arrays and results      */
     334            0 :         first_kid =     mxCallocInt (n+1);
     335            0 :         next_kid  =     mxCallocInt (n+1);
     336            0 :         post      =     mxCallocInt (n+1);
     337              : 
     338              :         /* Set up structure describing children */
     339            0 :         for (v = 0; v <= n; first_kid[v++] = -1);
     340            0 :         for (v = n-1; v >= 0; v--) {
     341            0 :                 dad = parent[v];
     342            0 :                 next_kid[v] = first_kid[dad];
     343            0 :                 first_kid[dad] = v;
     344              :         }
     345              : 
     346              :         /* Depth-first search from dummy root vertex #n */
     347              :         postnum = 0;
     348              : #if 0
     349              :         /* recursion */
     350              :         etdfs (n, first_kid, next_kid, post, &postnum);
     351              : #else
     352              :         /* no recursion */
     353            0 :         nr_etdfs(n, parent, first_kid, next_kid, post, postnum);
     354              : #endif
     355              : 
     356            0 :         SUPERLU_FREE (first_kid);
     357            0 :         SUPERLU_FREE (next_kid);
     358            0 :         return post;
     359              : }
     360              : 
     361              : 
     362              : /*
     363              :  *      p = spsymetree (A);
     364              :  *
     365              :  *      Find the elimination tree for symmetric matrix A.
     366              :  *      This uses Liu's algorithm, and runs in time O(nz*log n).
     367              :  *
     368              :  *      Input:
     369              :  *        Square sparse matrix A.  No check is made for symmetry;
     370              :  *        elements below and on the diagonal are ignored.
     371              :  *        Numeric values are ignored, so any explicit zeros are 
     372              :  *        treated as nonzero.
     373              :  *      Output:
     374              :  *        Integer array of parents representing the etree, with n
     375              :  *        meaning a root of the elimination forest.
     376              :  *      Note:  
     377              :  *        This routine uses only the upper triangle, while sparse
     378              :  *        Cholesky (as in spchol.c) uses only the lower.  Matlab's
     379              :  *        dense Cholesky uses only the upper.  This routine could
     380              :  *        be modified to use the lower triangle either by transposing
     381              :  *        the matrix or by traversing it by rows with auxiliary
     382              :  *        pointer and link arrays.
     383              :  *
     384              :  *      John R. Gilbert, Xerox, 10 Dec 1990
     385              :  *      Based on code by JRG dated 1987, 1988, and 1990.
     386              :  *      Modified by X.S. Li, November 1999.
     387              :  */
     388              : 
     389              : /*
     390              :  * Symmetric elimination tree
     391              :  */
     392            0 : int sp_symetree(
     393              :                 const int *acolst, const int *acolend, /* column starts and ends past 1 */
     394              :                 const int *arow,            /* row indices of A */
     395              :                 int n,                /* dimension of A */
     396              :                 int *parent)    /* parent in elim tree */
     397              : {
     398              :         int     *root;              /* root of subtree of etree         */
     399              :         int     rset, cset;             
     400              :         int     row, col;
     401              :         int     rroot;
     402              :         int     p;
     403              :         int     *pp;
     404              : 
     405            0 :         root = mxCallocInt (n);
     406              :         initialize_disjoint_sets (n, &pp);
     407              : 
     408            0 :         for (col = 0; col < n; col++) {
     409              :                 cset = make_set (col, pp);
     410            0 :                 root[cset] = col;
     411            0 :                 parent[col] = n; /* Matlab */
     412            0 :                 for (p = acolst[col]; p < acolend[col]; p++) {
     413            0 :                         row = arow[p];
     414            0 :                         if (row >= col) continue;
     415              :                         rset = find (row, pp);
     416            0 :                         rroot = root[rset];
     417            0 :                         if (rroot != col) {
     418            0 :                                 parent[rroot] = col;
     419              :                                 cset = link (cset, rset, pp);
     420            0 :                                 root[cset] = col;
     421              :                         }
     422              :                 }
     423              :         }
     424            0 :         SUPERLU_FREE (root);
     425              :         finalize_disjoint_sets (pp);
     426            0 :         return 0;
     427              : } /* SP_SYMETREE */
        

Generated by: LCOV version 2.0-1