1 /* ========================================================================= */
2 /* === AMD_valid =========================================================== */
3 /* ========================================================================= */
4 
5 /* ------------------------------------------------------------------------- */
6 /* AMD, Copyright (c) Timothy A. Davis,					     */
7 /* Patrick R. Amestoy, and Iain S. Duff.  See ../README.txt for License.     */
8 /* email: DrTimothyAldenDavis@gmail.com                                      */
9 /* ------------------------------------------------------------------------- */
10 
11 /* Check if a column-form matrix is valid or not.  The matrix A is
12  * n_row-by-n_col.  The row indices of entries in column j are in
13  * Ai [Ap [j] ... Ap [j+1]-1].  Required conditions are:
14  *
15  *	n_row >= 0
16  *	n_col >= 0
17  *	nz = Ap [n_col] >= 0	    number of entries in the matrix
18  *	Ap [0] == 0
19  *	Ap [j] <= Ap [j+1] for all j in the range 0 to n_col.
20  *      Ai [0 ... nz-1] must be in the range 0 to n_row-1.
21  *
22  * If any of the above conditions hold, AMD_INVALID is returned.  If the
23  * following condition holds, AMD_OK_BUT_JUMBLED is returned (a warning,
24  * not an error):
25  *
26  *	row indices in Ai [Ap [j] ... Ap [j+1]-1] are not sorted in ascending
27  *	    order, and/or duplicate entries exist.
28  *
29  * Otherwise, AMD_OK is returned.
30  *
31  * In v1.2 and earlier, this function returned TRUE if the matrix was valid
32  * (now returns AMD_OK), or FALSE otherwise (now returns AMD_INVALID or
33  * AMD_OK_BUT_JUMBLED).
34  */
35 
36 module amd_valid;
37 
38 nothrow @nogc extern(C):
39 
40 import amd_internal;
41 import amd;
42 import SuiteSparse_config;
43 
44 
45 /* ------------------------------------------------------------------------- */
46 /* amd_valid */
47 /* ------------------------------------------------------------------------- */
48 
49 /* Returns AMD_OK or AMD_OK_BUT_JUMBLED if the matrix is valid as input to
50  * amd_order; the latter is returned if the matrix has unsorted and/or
51  * duplicate row indices in one or more columns.  Returns AMD_INVALID if the
52  * matrix cannot be passed to amd_order.  For amd_order, the matrix must also
53  * be square.  The first two arguments are the number of rows and the number
54  * of columns of the matrix.  For its use in AMD, these must both equal n.
55  *
56  * NOTE: this routine returned TRUE/FALSE in v1.2 and earlier.
57  */
58 version (DLONG){
59     SuiteSparse_long AMD_valid
60     (
61 		/* inputs, not modified on output: */
62         SuiteSparse_long n_row,			/* A is n_row-by-n_col */
63         SuiteSparse_long n_col,
64         const SuiteSparse_long * Ap,	/* column pointers of A, of size n_col+1 */
65         const SuiteSparse_long * Ai		/* row indices of A, of size nz = Ap [n_col] */
66     )
67 	{
68 		Int nz, j, p1, p2, ilast, i, p, result = AMD_OK ;
69 
70 		if (n_row < 0 || n_col < 0 || Ap == NULL || Ai == NULL)
71 		{
72 		return (AMD_INVALID) ;
73 		}
74 		nz = Ap [n_col] ;
75 		if (Ap [0] != 0 || nz < 0)
76 		{
77 		/* column pointers must start at Ap [0] = 0, and Ap [n] must be >= 0 */
78 		AMD_DEBUG0 ("column 0 pointer bad or nz < 0\n");
79 		return (AMD_INVALID) ;
80 		}
81 		for (j = 0 ; j < n_col ; j++)
82 		{
83 		p1 = Ap [j] ;
84 		p2 = Ap [j+1] ;
85 		AMD_DEBUG2 ("\nColumn: "~ID~" p1: "~ID~" p2: "~ID~"\n", j, p1, p2) ;
86 		if (p1 > p2)
87 		{
88 			/* column pointers must be ascending */
89 			AMD_DEBUG0 ("column "~ID~" pointer bad\n", j) ;
90 			return (AMD_INVALID) ;
91 		}
92 		ilast = EMPTY ;
93 		for (p = p1 ; p < p2 ; p++)
94 		{
95 			i = Ai [p] ;
96 			AMD_DEBUG3 ("row: "~ID~"\n", i) ;
97 			if (i < 0 || i >= n_row)
98 			{
99 			/* row index out of range */
100 			AMD_DEBUG0 ("index out of range, col "~ID~" row "~ID~"\n", j, i);
101 			return (AMD_INVALID) ;
102 			}
103 			if (i <= ilast)
104 			{
105 			/* row index unsorted, or duplicate entry present */
106 			AMD_DEBUG1 ("index unsorted/dupl col "~ID~" row "~ID~"\n", j, i);
107 			result = AMD_OK_BUT_JUMBLED ;
108 			}
109 			ilast = i ;
110 		}
111 		}
112 		return (result) ;
113 	}
114 } // DLONG
115 else {
116     int AMD_valid
117     (
118 		/* inputs, not modified on output: */
119         int n_row,                 /* A is n_row-by-n_col */  /* # of rows */
120         int n_col,                 /* # of columns */
121         const int * Ap,          /* column pointers of A, of size n_col+1 */
122         const int * Ai           /* row indices of A, of size nz = Ap [n_col] */
123     )
124 	{
125 		Int nz, j, p1, p2, ilast, i, p, result = AMD_OK ;
126 
127 		if (n_row < 0 || n_col < 0 || Ap == NULL || Ai == NULL)
128 		{
129 		return (AMD_INVALID) ;
130 		}
131 		nz = Ap [n_col] ;
132 		if (Ap [0] != 0 || nz < 0)
133 		{
134 		/* column pointers must start at Ap [0] = 0, and Ap [n] must be >= 0 */
135 		AMD_DEBUG0 ("column 0 pointer bad or nz < 0\n");
136 		return (AMD_INVALID) ;
137 		}
138 		for (j = 0 ; j < n_col ; j++)
139 		{
140 		p1 = Ap [j] ;
141 		p2 = Ap [j+1] ;
142 		AMD_DEBUG2 ("\nColumn: "~ID~" p1: "~ID~" p2: "~ID~"\n", j, p1, p2) ;
143 		if (p1 > p2)
144 		{
145 			/* column pointers must be ascending */
146 			AMD_DEBUG0 ("column "~ID~" pointer bad\n", j) ;
147 			return (AMD_INVALID) ;
148 		}
149 		ilast = EMPTY ;
150 		for (p = p1 ; p < p2 ; p++)
151 		{
152 			i = Ai [p] ;
153 			AMD_DEBUG3 ("row: "~ID~"\n", i) ;
154 			if (i < 0 || i >= n_row)
155 			{
156 			/* row index out of range */
157 			AMD_DEBUG0 ("index out of range, col "~ID~" row "~ID~"\n", j, i);
158 			return (AMD_INVALID) ;
159 			}
160 			if (i <= ilast)
161 			{
162 			/* row index unsorted, or duplicate entry present */
163 			AMD_DEBUG1 ("index unsorted/dupl col "~ID~" row "~ID~"\n", j, i);
164 			result = AMD_OK_BUT_JUMBLED ;
165 			}
166 			ilast = i ;
167 		}
168 		}
169 		return (result) ;
170 	}
171 } // DLONG
172