SpM Handbook 1.3.0
Loading...
Searching...
No Matches
d_spm_get_diagonal_zeros.c
Go to the documentation of this file.
1/**
2 *
3 * @file d_spm_get_diagonal_zeros.c
4 *
5 * SParse Matrix package precision dependent routines to detect zero diagonal
6 * entries.
7 *
8 * @copyright 2016-2026 Bordeaux INP, CNRS (LaBRI UMR 5800), Inria,
9 * Univ. Bordeaux. All rights reserved.
10 *
11 * @version 1.3.0
12 * @author Fatima-Zahra Salhi
13 * @date 2026-07-09
14 *
15 * @generated from /builds/fpruvost/spm/src/z_spm_get_diagonal_zeros.c, normal z -> d, Fri Oct 23 13:04:59 2026
16 *
17 * @ingroup spm_dev_zeros
18 * @{
19 *
20 **/
21#include "common.h"
22
23/**
24 *******************************************************************************
25 *
26 * @ingroup spm_dev_zeros
27 *
28 * @brief Scan a CSC or CSR matrix for zero or missing diagonal entries.
29 *
30 *******************************************************************************
31 *
32 * @param[in] spm
33 * The sparse matrix, in SpmCSC or SpmCSR format.
34 *
35 * @param[inout] zeros_n
36 * On entry, the capacity of zeros_list. On exit, the number of zero
37 * or missing diagonal entries.
38 *
39 * @param[inout] zeros_list
40 * On entry, a pre-allocated array of size *zeros_n. On exit, the
41 * first *zeros_n entries contain the indices of the zero or missing
42 * diagonal entries. The array may be reallocated.
43 *
44 *******************************************************************************
45 *
46 * @retval SPM_SUCCESS
47 * On success.
48 *
49 * @retval SPM_ERR_OUTOFMEMORY
50 * If zeros_list could not be enlarged.
51 *
52 *******************************************************************************/
53
54static inline int
56 spm_int_t *zeros_n,
57 spm_int_t **zeros_list )
58{
59 const double *values = spm->values;
60 const spm_int_t *colptr;
61 const spm_int_t *rowptr;
62 spm_int_t baseval = spmFindBase( spm );
63 spm_int_t size = *zeros_n;
64 spm_int_t i, j;
65
66 assert( (spm->fmttype == SpmCSC) ||
67 (spm->fmttype == SpmCSR) );
68 if ( spm->fmttype == SpmCSC ) {
69 colptr = spm->colptr;
70 rowptr = spm->rowptr;
71 }
72 else {
73 colptr = spm->rowptr;
74 rowptr = spm->colptr;
75 }
76
77 *zeros_n = 0;
78 for ( i=0; i<spm->n; i++ )
79 {
80 int has_nonzero_diag = 0;
81
82 spm_int_t begin = colptr[i] - baseval;
83 spm_int_t end = colptr[i + 1] - baseval;
84 spm_int_t diag = i + baseval;
85
86 for ( j=begin; j<end; j++ )
87 {
88 if ( rowptr[j] == diag ) {
89 has_nonzero_diag = (values[j] != (double)0.0);
90 break;
91 }
92 }
93
94 /*
95 * If the diagonal entry is missing, has_nonzero_diag remains false.
96 */
97 if ( !has_nonzero_diag ) {
98 if ( *zeros_n == size ) {
99 spm_int_t newsize = spm_imin( 2 * size, spm->n );
100 spm_int_t *newlist;
101
102 newlist = realloc( *zeros_list,
103 newsize * sizeof( spm_int_t ) );
104 if ( newlist == NULL ) {
105 return SPM_ERR_OUTOFMEMORY;
106 }
107 *zeros_list = newlist;
108 size = newsize;
109 }
110 (*zeros_list)[(*zeros_n)++] = diag;
111 }
112 }
113
114 return SPM_SUCCESS;
115}
116
117/**
118 *******************************************************************************
119 *
120 * @ingroup spm_dev_zeros
121 *
122 * @brief Detect unknowns with a zero or missing diagonal entry
123 *
124 * @param[in] spm
125 * The sparse matrix, in SpmCSC or SpmCSR format.
126 *
127 * @param[out] zeros_n
128 * On exit, the number of unknowns whose diagonal entry is zero
129 * or absent.
130 *
131 * @param[out] zeros_list
132 * On exit, pointer to an array containing the baseval-indexed
133 * indices of the affected unknowns. Set to NULL when zeros_n is 0
134 * or when the function fails. The caller is responsible for freeing
135 * this array.
136 *
137 *******************************************************************************
138 *
139 * @retval SPM_SUCCESS
140 * On success.
141 *
142 * @retval SPM_ERR_BADPARAMETER
143 * If spm->fmttype is neither SpmCSC nor SpmCSR.
144 *
145 * @retval SPM_ERR_OUTOFMEMORY
146 * If the allocation of zeros_list failed.
147 *
148 *******************************************************************************/
149
150int
152 spm_int_t *zeros_n,
153 spm_int_t **zeros_list )
154{
155 spm_int_t *newlist;
156 int rc;
157
158 *zeros_n = 0;
159 *zeros_list = NULL;
160
161 if ( (spm->fmttype != SpmCSC) &&
162 (spm->fmttype != SpmCSR) )
163 {
165 }
166
167 if ( spm->n == 0 ) {
168 return SPM_SUCCESS;
169 }
170
171 *zeros_n = spm_imax( 1, spm->n / 20 );
172 *zeros_list = malloc( (*zeros_n) * sizeof( spm_int_t ) );
173 if ( *zeros_list == NULL ) {
174 *zeros_n = 0;
175 return SPM_ERR_OUTOFMEMORY;
176 }
177
178 switch (spm->fmttype) {
179 case SpmCSC:
180 case SpmCSR:
181 rc = d_spm_get_diagonal_zeros_csx( spm, zeros_n, zeros_list );
182 break;
183 case SpmIJV:
184 fprintf( stderr, "spmGetDiagonalZeros: Unsupported for IJV matrices\n");
186 break;
187 }
188
189 if ( rc != SPM_SUCCESS ) {
190 free( *zeros_list );
191 *zeros_list = NULL;
192 *zeros_n = 0;
193 return rc;
194 }
195
196 /* Resize zeros_list to the exact number of entries */
197 if ( *zeros_n == 0 ) {
198 free( *zeros_list );
199 *zeros_list = NULL;
200 }
201 else {
202 newlist = realloc( *zeros_list,
203 *zeros_n * sizeof( spm_int_t ) );
204 if ( newlist == NULL ) {
205 free( *zeros_list );
206 *zeros_list = NULL;
207 *zeros_n = 0;
208 return SPM_ERR_OUTOFMEMORY;
209 }
210 *zeros_list = newlist;
211 }
212
213 return SPM_SUCCESS;
214}
215
216/**
217 * @}
218 */
static spm_int_t spm_imin(spm_int_t a, spm_int_t b)
Internal function to compute min(a,b).
Definition datatypes.h:97
static spm_int_t spm_imax(spm_int_t a, spm_int_t b)
Internal function to compute max(a,b).
Definition datatypes.h:119
@ SPM_ERR_BADPARAMETER
Definition const.h:89
@ SPM_SUCCESS
Definition const.h:82
@ SPM_ERR_OUTOFMEMORY
Definition const.h:86
@ SPM_ERR_NOTIMPLEMENTED
Definition const.h:85
@ SpmCSC
Definition const.h:73
@ SpmCSR
Definition const.h:74
@ SpmIJV
Definition const.h:75
static int d_spm_get_diagonal_zeros_csx(const spmatrix_t *spm, spm_int_t *zeros_n, spm_int_t **zeros_list)
Scan a CSC or CSR matrix for zero or missing diagonal entries.
int d_spmGetDiagonalZeros(const spmatrix_t *spm, spm_int_t *zeros_n, spm_int_t **zeros_list)
Detect unknowns with a zero or missing diagonal entry.
void * values
Definition spm.h:93
spm_int_t * rowptr
Definition spm.h:91
spm_fmttype_t fmttype
Definition spm.h:70
spm_int_t n
Definition spm.h:74
spm_int_t * colptr
Definition spm.h:90
struct spmatrix_s spmatrix_t
The sparse matrix data structure.
spm_int_t spmFindBase(const spmatrix_t *spm)
Search the base used in the spm structure.
Definition spm.c:358
int spm_int_t
The main integer datatype used in spm arrays.
Definition datatypes.h:70