LADEL main
Sparse LDL factorization package with rank 1 and rowadd/rowdel updates
ladel_col_counts.c
Go to the documentation of this file.
1#include "ladel_types.h"
2#include "ladel_constants.h"
3#include "ladel_transpose.h"
4#include "ladel_global.h"
5#include "ladel_debug_print.h"
6
7#define FIRST_LEAF 1
8#define SUBSEQUENT_LEAF 2
9#define NOT_A_LEAF -1
10
12 ladel_int *max_first_descendant, ladel_int *prev_leaf,
13 ladel_int *ancestor, ladel_int *node_type_of_leaf)
14{
15 if (subtree_root <= node || first_descendant[node] <= max_first_descendant[subtree_root])
16 {
17 *node_type_of_leaf = NOT_A_LEAF;
18 return NONE;
19 } else
20 {
21 max_first_descendant[subtree_root] = first_descendant[node];
22
23 ladel_int last_leaf = prev_leaf[subtree_root];
24 prev_leaf[subtree_root] = node;
25 if (last_leaf == NONE)
26 {
27 *node_type_of_leaf = FIRST_LEAF;
28 return node;
29 } else
30 {
31 *node_type_of_leaf = SUBSEQUENT_LEAF;
32
33 ladel_int lca; /*least common ancestor*/
34 for (lca = last_leaf; lca != ancestor[lca]; lca = ancestor[lca]);
35
36 ladel_int last_path_node, ancestor_of_last_path_node;
37 for (last_path_node = last_leaf; last_path_node != lca; last_path_node = ancestor_of_last_path_node)
38 {
39 ancestor_of_last_path_node = ancestor[last_path_node];
40 ancestor[last_path_node] = lca;
41 }
42 return lca;
43 }
44 }
45
46}
47
49{
50 if (!M || !sym || !sym->etree || !sym->postorder || !sym->col_counts || !work) return FAIL;
51
52 ladel_int *etree = sym->etree, *postorder = sym->postorder, *col_counts = sym->col_counts;
53 ladel_int *prev_leaf = work->array_int_ncol1;
54 ladel_int *first_descendant = work->array_int_ncol2;
55 ladel_int *max_first_descendant = work->array_int_ncol3;
56 ladel_int *ancestor = work->array_int_ncol4;
57 ladel_int ncol = M->ncol, index, node, post_node, subtree_root, lca, type_of_leaf = NOT_A_LEAF;
58
59 ladel_sparse_matrix *M_lower;
60 if (M->symmetry == UPPER) M_lower = ladel_transpose(M, FALSE, work);
61 else if (M->symmetry == LOWER) M_lower = M;
62 else return FAIL;
63
64 if (!M_lower) return FAIL;
65
66 for (index = 0; index < ncol; index++) prev_leaf[index] = NONE;
67 for (index = 0; index < ncol; index++) first_descendant[index] = NONE;
68 for (index = 0; index < ncol; index++) max_first_descendant[index] = NONE;
69 for (index = 0; index < ncol; index++) ancestor[index] = index;
70
71 for (node = 0; node < ncol; node++)
72 {
73 post_node = postorder[node];
74 if (first_descendant[post_node] == NONE)
75 col_counts[post_node] = 1;
76 else
77 col_counts[post_node] = 0;
78 for (; post_node != NONE && first_descendant[post_node] == NONE; post_node = etree[post_node])
79 first_descendant[post_node] = node;
80 }
81 for (node = 0; node < ncol; node++)
82 {
83 post_node = postorder[node];
84 if (!IS_ROOT(post_node, etree)) col_counts[etree[post_node]]--;
85 LADEL_FOR(index, M_lower, post_node)
86 {
87 subtree_root = M_lower->i[index];
88 lca = ladel_least_common_ancestor(subtree_root, post_node, first_descendant, max_first_descendant, prev_leaf, ancestor, &type_of_leaf);
89 if (type_of_leaf != NOT_A_LEAF) col_counts[post_node]++;
90 if (type_of_leaf == SUBSEQUENT_LEAF) col_counts[lca]--; /*correct for duplicates*/
91 }
92 if (!IS_ROOT(post_node, etree)) ancestor[post_node] = etree[post_node];
93 }
94 for (node = 0; node < ncol; node++)
95 if (!IS_ROOT(node, etree)) col_counts[etree[node]] += col_counts[node];
96
97 for (node = 1; node < ncol; node++)
98 {
99 col_counts[node] += --col_counts[node-1];
100 }
101 col_counts[ncol-1]--;
102
103 if (M->symmetry == UPPER) ladel_sparse_free(M_lower);
104 return col_counts[ncol-1];
105}
#define NONE
Indicates a root (a node without parent), or an untouched node.
#define FALSE
For booleans.
#define LOWER
Use only lower part of matrix.
#define UPPER
Use only upper part of matrix.
#define FAIL
For status returns.
#define LADEL_FOR(index, M, col)
Loop through a column of a sparse matrix.
#define IS_ROOT(col, etree)
Check whether a node is a root (i.e.
#define NOT_A_LEAF
ladel_int ladel_least_common_ancestor(ladel_int subtree_root, ladel_int node, ladel_int *first_descendant, ladel_int *max_first_descendant, ladel_int *prev_leaf, ladel_int *ancestor, ladel_int *node_type_of_leaf)
ladel_int ladel_col_counts(ladel_sparse_matrix *M, ladel_symbolics *sym, ladel_work *work)
Computes the column counts of the factor.
#define SUBSEQUENT_LEAF
#define FIRST_LEAF
Constants and macros used in LADEL.
Routines to print out matrices and vectors.
Memory allocation routines.
ladel_sparse_matrix * ladel_sparse_free(ladel_sparse_matrix *M)
Free a sparse matrix (and return NULL).
Definition: ladel_global.c:91
Routine to compute the transpose of a matrix.
ladel_sparse_matrix * ladel_transpose(ladel_sparse_matrix *M, ladel_int values, ladel_work *work)
Returns the transpose of a matrix, that is .
Structures and types used in LADEL routines.
int64_t ladel_int
Type for integer numbers (default: int64_t)
Definition: ladel_types.h:24
Sparse matrix in compressed column storage.
Definition: ladel_types.h:35
ladel_int symmetry
type of symmetry (UNSYMMETRIC, UPPER or LOWER)
Definition: ladel_types.h:46
ladel_int ncol
number of columns
Definition: ladel_types.h:38
ladel_int * i
row pointers (size nzmax)
Definition: ladel_types.h:41
Structure capturing symbolic information used for and during the factorization.
Definition: ladel_types.h:54
ladel_int * etree
eliminations tree
Definition: ladel_types.h:56
ladel_int * postorder
postordiring of the elimination tree
Definition: ladel_types.h:57
ladel_int * col_counts
column counts, stored as column pointers
Definition: ladel_types.h:58
Workspace required for various routines in LADEL.
Definition: ladel_types.h:109
ladel_int * array_int_ncol2
An array of ncol integers.
Definition: ladel_types.h:117
ladel_int * array_int_ncol1
An array of ncol integers.
Definition: ladel_types.h:116
ladel_int * array_int_ncol3
An array of ncol integers.
Definition: ladel_types.h:118
ladel_int * array_int_ncol4
An array of ncol integers.
Definition: ladel_types.h:119