SpM Handbook 1.2.4
Loading...
Searching...
No Matches
spm.h
Go to the documentation of this file.
1/**
2 *
3 * @file spm.h
4 *
5 * SParse Matrix package header.
6 *
7 * @copyright 2016-2024 Bordeaux INP, CNRS (LaBRI UMR 5800), Inria,
8 * Univ. Bordeaux. All rights reserved.
9 *
10 * @version 1.2.4
11 * @author Mathieu Faverge
12 * @author Pierre Ramet
13 * @author Tony Delarue
14 * @author Matias Hastaran
15 * @author Florent Pruvost
16 * @date 2024-06-25
17 *
18 **/
19#ifndef _spm_h_
20#define _spm_h_
21
22#include <stdlib.h>
23#include <assert.h>
24#include <stdio.h>
25#include "spm/config.h"
26#include "spm/const.h"
27#include "spm/datatypes.h"
28#include "spm/mpi.h"
29
30#include "spm/z_spm.h"
31#include "spm/c_spm.h"
32#include "spm/d_spm.h"
33#include "spm/s_spm.h"
34#include "spm/p_spm.h"
35
36BEGIN_C_DECLS
37
38/**
39 * @addtogroup spm
40 * @{
41 * @brief Describe all the internals routines of the SParse Matrix package.
42 *
43 * This library provides a set of subroutines to manipulate sparse matrices in
44 * different format such as compressed sparse column (CSC), compressed sparse
45 * row (CSR), or coordinate (IJV) with single or multiple degrees of freedom
46 * per unknown. It provides basic BLAS 1 and BLAS 2 functions for those
47 * matrices, as well as norms computations and converter tools.
48 */
49
50/**
51 *
52 * @brief The sparse matrix data structure
53 *
54 * This structure describes matrices with different characteristics that can be useful to any
55 * solver:
56 * - the storage format (SpmCSC, SpmCSR or SpmIJV)
57 * - the properties (SpmGeneral, SpmHermitian, SpmSymmetric)
58 * - the base value (0 in C or 1 in Fortran)
59 *
60 * All arrays indicated with [+baseval] are using indices in the baseval numbering (C, or Fortran).
61 * It is also possible to describe a matrix with constant or variable degrees of freedom.
62 *
63 */
64typedef struct spmatrix_s {
65 spm_mtxtype_t mtxtype; /**< Matrix structure: SpmGeneral, SpmSymmetric
66 or SpmHermitian. */
67 spm_coeftype_t flttype; /**< values datatype: SpmPattern, SpmFloat, SpmDouble,
68 SpmComplex32 or SpmComplex64 */
69 spm_fmttype_t fmttype; /**< Matrix storage format: SpmCSC, SpmCSR, SpmIJV */
70
71 spm_int_t baseval; /**< The base value [C, Fortran] of the indices in the arrays */
72 spm_int_t gN; /**< Global number of vertices in the compressed graph (Computed) */
73 spm_int_t n; /**< Local number of vertices in the compressed graph */
74 spm_int_t gnnz; /**< Global number of non zeroes in the compressed graph (Computed) */
75 spm_int_t nnz; /**< Local number of non zeroes in the compressed graph */
76
77 spm_int_t gNexp; /**< Global number of vertices in the compressed graph (Computed) */
78 spm_int_t nexp; /**< Local number of vertices in the compressed graph (Computed) */
79 spm_int_t gnnzexp; /**< Global number of non zeroes in the compressed graph (Computed) */
80 spm_int_t nnzexp; /**< Local number of non zeroes in the compressed graph (Computed) */
81
82 spm_int_t dof; /**< Number of degrees of freedom per unknown,
83 if > 0, constant degree of freedom
84 otherwise, irregular degree of freedom (refer to dofs) */
85 spm_int_t *dofs; /**< Array of the first column of each element in the
86 expanded matrix [+baseval] */
87 spm_layout_t layout; /**< SpmColMajor, or SpmRowMajor */
88
89 spm_int_t *colptr; /**< List of indirections to rows for each vertex [+baseval] */
90 spm_int_t *rowptr; /**< List of edges for each vertex [+baseval] */
91 spm_int_t *loc2glob;/**< Corresponding numbering from local to global [+baseval] */
92 void *values; /**< Values stored in the matrix */
93
94 spm_int_t *glob2loc; /**< Corresponding numbering from global to local [0-based], -(owner+1) if remote */
95 int clustnum; /**< Rank of the MPI node */
96 int clustnbr; /**< Number of MPI nodes in the communicator */
97 SPM_Comm comm; /**< Spm communicator to exhange datas */
98 int replicated; /**< 0 if the matrix is distributed, 1 if it is replicated on all nodes */
100
101/**
102 * @name SPM basic subroutines
103 * @{
104 */
105void spmInit( spmatrix_t *spm );
106void spmInitDist( spmatrix_t *spm, SPM_Comm comm );
107void spmAlloc( spmatrix_t *spm );
108void spmExit( spmatrix_t *spm );
109
110void spmCopy( const spmatrix_t *spm_in, spmatrix_t *spm_out );
111void spmBase( spmatrix_t *spm, int baseval );
112spm_int_t spmFindBase( const spmatrix_t *spm );
113spm_int_t spmGetDegree( const spmatrix_t *spm );
114int spmConvert( int ofmttype, spmatrix_t *ospm );
116void spmGenFakeValues( spmatrix_t *spm );
117
118/**
119 * @}
120 * @name SPM distribution subroutines
121 * @{
122 */
123int spmScatter( spmatrix_t *spm_scattered,
124 int root,
125 const spmatrix_t *opt_spm_gathered,
126 spm_int_t opt_n,
127 const spm_int_t *opt_loc2glob,
128 int opt_distByColumn,
129 SPM_Comm opt_comm );
130int spmGather( const spmatrix_t *spm_scattered,
131 int root,
132 spmatrix_t *opt_spm_gathered );
133int spmGatherInPlace( spmatrix_t *spm );
134int spmRedistribute( const spmatrix_t *spm,
135 spm_int_t new_n,
136 const spm_int_t *newl2g,
137 spmatrix_t *newspm );
138
139/**
140 * @}
141 * @name SPM BLAS subroutines
142 * @{
143 */
144double spmNorm ( spm_normtype_t ntype, const spmatrix_t *spm );
145double spmNormVec( spm_normtype_t ntype, const spmatrix_t *spm, const void *x, spm_int_t incx );
146double spmNormMat( spm_normtype_t ntype, const spmatrix_t *spm, spm_int_t n, const void *A, spm_int_t lda );
147
148int spmMatVec( spm_trans_t trans, double alpha, const spmatrix_t *spm, const void *x, double beta, void *y );
149int spmMatMat( spm_trans_t trans, spm_int_t n,
150 double alpha, const spmatrix_t *A,
151 const void *B, spm_int_t ldb,
152 double beta, void *C, spm_int_t ldc );
153
154void spmScal ( double alpha, spmatrix_t *spm );
155void spmScalVec( double alpha, const spmatrix_t *spm, void *x, spm_int_t incx );
156void spmScalMat( double alpha, const spmatrix_t *spm, spm_int_t n, void *A, spm_int_t lda );
157
158void spmScalMatrix( double alpha, spmatrix_t *spm ) __attribute__((__deprecated__("Please replace by spmScal() function (will be removed in 1.3.0)")));
159void spmScalVector( spm_coeftype_t flt, double alpha, spm_int_t n, void *A, spm_int_t lda ) __attribute__((__deprecated__("Please replace by spmScalVec() or spmScalMat() depending on usage (will be removed in 1.3.0)")));
160
161/**
162 * @}
163 * @name SPM subroutines to check format
164 * @{
165 */
166int spmSort( spmatrix_t *spm );
169int spmCheckAndCorrect( const spmatrix_t *spm_in, spmatrix_t *spm_out );
170
171/**
172 * @}
173 * @name SPM subroutines to check factorization/solve
174 * @{
175 */
176int spmGenMat( spm_rhstype_t type,
177 spm_int_t nrhs,
178 const spmatrix_t *spm,
179 void *alpha,
180 unsigned long long int seed,
181 void *A,
182 spm_int_t lda );
183int spmGenVec( spm_rhstype_t type,
184 const spmatrix_t *spm,
185 void *alpha,
186 unsigned long long int seed,
187 void *x,
188 spm_int_t incx );
189int spmGenRHS( spm_rhstype_t type,
190 spm_int_t nrhs,
191 const spmatrix_t *spm,
192 void * opt_X,
193 spm_int_t opt_ldx,
194 void * B,
195 spm_int_t ldb );
196int spmCheckAxb( double eps,
197 spm_int_t nrhs,
198 const spmatrix_t *spm,
199 void * opt_X0,
200 spm_int_t opt_ldx0,
201 void * B,
202 spm_int_t ldb,
203 const void * X,
204 spm_int_t ldx );
205
206/**
207 * @}
208 * @name SPM subroutines to manipulate RHS
209 * @{
210 */
212 const spmatrix_t *spm,
213 const void *Bg,
214 spm_int_t ldbg,
215 void *Bl,
216 spm_int_t ldbl );
217int spmReduceRHS( spm_int_t nrhs,
218 const spmatrix_t *spm,
219 void *Bg,
220 spm_int_t ldbg,
221 void *Bl,
222 spm_int_t ldbl );
223int spmGatherRHS( spm_int_t nrhs,
224 const spmatrix_t *spm,
225 const void *Bl,
226 spm_int_t ldbl,
227 int root,
228 void *Bg,
229 spm_int_t ldbg );
230
231/**
232 * @}
233 * @name SPM subroutines to manipulate integers arrays
234 * @{
235 */
236void spmIntConvert( spm_int_t n, const int *input, spm_int_t *output );
237void spmIntSort1Asc1( void *const pbase, spm_int_t n );
238void spmIntSort2Asc1( void *const pbase, spm_int_t n );
239void spmIntSort2Asc2( void *const pbase, spm_int_t n );
240void spmIntMSortIntAsc( void **const pbase, spm_int_t n );
241
242/**
243 * @}
244 * @name SPM IO subroutines
245 * @{
246 */
247int spmLoadDist( spmatrix_t *spm, const char *filename, SPM_Comm comm );
248int spmLoad( spmatrix_t *spm, const char *filename );
249int spmSave( const spmatrix_t *spm, const char *filename );
250
251/**
252 * @}
253 * @name SPM driver
254 * @{
255 */
256int spmReadDriver ( spm_driver_t driver,
257 const char *filename,
258 spmatrix_t *spm );
260 const char *filename,
261 spmatrix_t *spm,
262 SPM_Comm comm );
263
264int spmParseLaplacianInfo( const char *filename,
265 spm_coeftype_t *flttype,
266 spm_int_t *dim1,
267 spm_int_t *dim2,
268 spm_int_t *dim3,
269 double *alpha,
270 double *beta,
271 spm_int_t *dof );
272
273/**
274 * @}
275 * @name SPM debug subroutines
276 * @{
277 */
278void spm2Dense( const spmatrix_t *spm, void *A );
279void spmPrint( const spmatrix_t *spm, FILE *f );
280void spmPrintRHS( const spmatrix_t *spm, int nrhs, const void *x, spm_int_t ldx, FILE *stream );
281void spmPrintInfo( const spmatrix_t *spm, FILE *f );
282void spmExpand( const spmatrix_t *spm_in, spmatrix_t *spm_out );
283int spmDofExtend( const spmatrix_t *spm, int type, int dof, spmatrix_t *spm_out );
284
285/**
286 * @}
287 * @}
288 * @name SPM dev printing subroutines
289 * @{
290 *
291 */
292
293/**
294 * @ingroup spm_dev_print
295 * @brief Subroutines to print one element of an spm structure
296 *
297 * @param[in] f Pointer to the file
298 * @param[in] i Row index of the element
299 * @param[in] j Column index of the element
300 * @param[in] A Value of the element A|i,j]
301 *
302 * Double complex case
303 *
304 */
305static inline void
306z_spmPrintElt( FILE *f, spm_int_t i, spm_int_t j, spm_complex64_t A )
307{
308 fprintf( f, "%ld %ld %e %e\n", (long)i, (long)j, creal( A ), cimag( A ) );
309}
310
311/**
312 * @copydoc z_spmPrintElt
313 * @details Single complex case
314 */
315static inline void
317{
318 fprintf( f, "%ld %ld %e %e\n", (long)i, (long)j, crealf( A ), cimagf( A ) );
319}
320/**
321 * @copydoc z_spmPrintElt
322 * @details Double real case
323 */
324static inline void
325d_spmPrintElt( FILE *f, spm_int_t i, spm_int_t j, double A )
326{
327 fprintf( f, "%ld %ld %e\n", (long)i, (long)j, A );
328}
329/**
330 * @copydoc z_spmPrintElt
331 * @details Single real case
332 */
333static inline void
334s_spmPrintElt( FILE *f, spm_int_t i, spm_int_t j, float A )
335{
336 fprintf( f, "%ld %ld %e\n", (long)i, (long)j, A );
337}
338/**
339 * @copydoc z_spmPrintElt
340 * @details Pattern case
341 *
342 * @remark: uses a macro to avoid accessing A that would generate segfault.
343 */
344#define p_spmPrintElt( f, i, j, A ) \
345 { \
346 fprintf( f, "%ld %ld\n", (long)( i ), (long)( j ) ); \
347 }
348
349/**
350 * @}
351 */
352
353/*
354 * Functions to handle number of Blas threads.
355 */
356int spmBlasGetNumThreads(void);
357int spmBlasSetNumThreads( int nt );
359
360END_C_DECLS
361
362#endif /* _spm_h_ */
float _Complex spm_complex32_t
Definition datatypes.h:161
enum spm_driver_e spm_driver_t
The list of matrix driver readers and generators.
enum spm_layout_e spm_layout_t
Direction of the matrix storage.
enum spm_fmttype_e spm_fmttype_t
Sparse matrix format.
enum spm_rhstype_e spm_rhstype_t
How to generate RHS.
enum spm_coeftype_e spm_coeftype_t
Arithmetic types.
enum spm_normtype_e spm_normtype_t
Norms.
enum spm_trans_e spm_trans_t
Transpostion.
enum spm_mtxtype_e spm_mtxtype_t
Matrix symmetry type property.
static void z_spmPrintElt(FILE *f, spm_int_t i, spm_int_t j, spm_complex64_t A)
Subroutines to print one element of an spm structure.
Definition spm.h:306
spm_coeftype_t flttype
Definition spm.h:67
spm_int_t * dofs
Definition spm.h:85
spm_int_t nexp
Definition spm.h:78
void * values
Definition spm.h:92
int clustnbr
Definition spm.h:96
spm_int_t nnz
Definition spm.h:75
spm_int_t nnzexp
Definition spm.h:80
spm_int_t * rowptr
Definition spm.h:90
spm_int_t gnnz
Definition spm.h:74
spm_fmttype_t fmttype
Definition spm.h:69
spm_int_t dof
Definition spm.h:82
spm_int_t n
Definition spm.h:73
spm_mtxtype_t mtxtype
Definition spm.h:65
spm_int_t * loc2glob
Definition spm.h:91
spm_layout_t layout
Definition spm.h:87
SPM_Comm comm
Definition spm.h:97
spm_int_t baseval
Definition spm.h:71
spm_int_t * glob2loc
Definition spm.h:94
spm_int_t gnnzexp
Definition spm.h:79
spm_int_t * colptr
Definition spm.h:89
spm_int_t gNexp
Definition spm.h:77
int clustnum
Definition spm.h:95
spm_int_t gN
Definition spm.h:72
int replicated
Definition spm.h:98
int spmGather(const spmatrix_t *spm_scattered, int root, spmatrix_t *opt_spm_gathered)
Gather a distributed Sparse Matrix on a single node.
Definition spm_gather.c:436
int spmParseLaplacianInfo(const char *filename, spm_coeftype_t *flttype, spm_int_t *dim1, spm_int_t *dim2, spm_int_t *dim3, double *alpha, double *beta, spm_int_t *dof)
Parse information given through the filename string to configure the laplacian matrix to generate.
Definition laplacian.c:96
double spmNormMat(spm_normtype_t ntype, const spmatrix_t *spm, spm_int_t n, const void *A, spm_int_t lda)
Compute the norm of the spm.
Definition spm.c:692
void spmAlloc(spmatrix_t *spm)
Allocate the arrays of an spm structure.
Definition spm.c:175
int spmLoadDist(spmatrix_t *spm, const char *filename, SPM_Comm comm)
Load the spm structure from a file (internal format).
Definition spm_io.c:664
void spmExit(spmatrix_t *spm)
Cleanup the spm structure but do not free the spm pointer.
Definition spm.c:224
int spmLoad(spmatrix_t *spm, const char *filename)
Load the spm structure from a file (internal format).
Definition spm_io.c:749
spm_int_t spmSymmetrize(spmatrix_t *spm)
Symmetrize the pattern of the spm.
int spmReduceRHS(spm_int_t nrhs, const spmatrix_t *spm, void *Bg, spm_int_t ldbg, void *Bl, spm_int_t ldbl)
Reduce an RHS thanks to spm distribution.
Definition spm_rhs.c:273
void spmUpdateComputedFields(spmatrix_t *spm)
Update all the computed fields based on the static values stored.
int spmGenRHS(spm_rhstype_t type, spm_int_t nrhs, const spmatrix_t *spm, void *opt_X, spm_int_t opt_ldx, void *B, spm_int_t ldb)
Generate right hand side vectors associated to a given matrix.
Definition spm_rhs.c:124
void spmBase(spmatrix_t *spm, int baseval)
Rebase the arrays of the spm to the given value.
Definition spm.c:271
struct spmatrix_s spmatrix_t
The sparse matrix data structure.
int spmScatter(spmatrix_t *spm_scattered, int root, const spmatrix_t *opt_spm_gathered, spm_int_t opt_n, const spm_int_t *opt_loc2glob, int opt_distByColumn, SPM_Comm opt_comm)
Scatter the SPM thanks to loc2glob.
int spm_int_t
The main integer datatype used in spm arrays.
Definition datatypes.h:70
spm_int_t spmFindBase(const spmatrix_t *spm)
Search the base used in the spm structure.
Definition spm.c:347
int spmMatVec(spm_trans_t trans, double alpha, const spmatrix_t *spm, const void *x, double beta, void *y)
Compute a matrix-vector product.
Definition spm.c:1234
void spmPrintRHS(const spmatrix_t *spm, int nrhs, const void *x, spm_int_t ldx, FILE *stream)
Print a set of vector associated to an spm matrix.
Definition spm_rhs.c:45
int spmCheckAxb(double eps, spm_int_t nrhs, const spmatrix_t *spm, void *opt_X0, spm_int_t opt_ldx0, void *B, spm_int_t ldb, const void *X, spm_int_t ldx)
Check the backward error, and the forward error if x0 is provided.
Definition spm.c:1423
void spmInitDist(spmatrix_t *spm, SPM_Comm comm)
Init the spm structure with a specific communicator.
Definition spm.c:101
int spmConvert(int ofmttype, spmatrix_t *ospm)
Convert the storage format of the spm.
Definition spm.c:418
int spmExtractLocalRHS(spm_int_t nrhs, const spmatrix_t *spm, const void *Bg, spm_int_t ldbg, void *Bl, spm_int_t ldbl)
Stores the local values of a global RHS in the local one thanks to spm distribution.
Definition spm_rhs.c:193
int spmGatherRHS(spm_int_t nrhs, const spmatrix_t *spm, const void *Bl, spm_int_t ldbl, int root, void *Bg, spm_int_t ldbg)
Gather an RHS thanks to spm distribution.
Definition spm_rhs.c:356
double spmNormVec(spm_normtype_t ntype, const spmatrix_t *spm, const void *x, spm_int_t incx)
Compute the norm of the spm.
Definition spm.c:596
spm_int_t spmMergeDuplicate(spmatrix_t *spm)
Merge multiple entries in a spm by summing their values together.
Definition spm.c:796
int spmMatMat(spm_trans_t trans, spm_int_t n, double alpha, const spmatrix_t *A, const void *B, spm_int_t ldb, double beta, void *C, spm_int_t ldc)
Compute a matrix-matrix product.
Definition spm.c:1327
void spmGenFakeValues(spmatrix_t *spm)
Generate the fake values array such that .
int spmRedistribute(const spmatrix_t *spm, spm_int_t new_n, const spm_int_t *newl2g, spmatrix_t *newspm)
Create a copy of a given SPM with a new distribution corresponding to the given loc2glob array.
int spmCheckAndCorrect(const spmatrix_t *spm_in, spmatrix_t *spm_out)
Check the correctness of a spm.
Definition spm.c:877
int spmGatherInPlace(spmatrix_t *spm)
This routine performs a allgather of a distributed spm in place.
Definition spm_gather.c:565
int spmReadDriver(spm_driver_t driver, const char *filename, spmatrix_t *spm)
Import a matrix file into a spm structure.
int spmSort(spmatrix_t *spm)
Sort the subarray of edges of each vertex.
Definition spm.c:746
void spmScal(double alpha, spmatrix_t *spm)
Scale the spm.
Definition spm.c:1481
void spmExpand(const spmatrix_t *spm_in, spmatrix_t *spm_out)
Expand a multi-dof spm matrix into an spm with constant dof set to 1.
Definition spm.c:1168
int spmDofExtend(const spmatrix_t *spm, int type, int dof, spmatrix_t *spm_out)
Generate a random multidof spm from a given spm (with dof=1).
void spmPrint(const spmatrix_t *spm, FILE *f)
Print an spm matrix into into a given file.
Definition spm.c:1119
void spmScalVec(double alpha, const spmatrix_t *spm, void *x, spm_int_t incx)
Scale a vector associated to a sparse matrix. Deprecated function replaced by spmScalVec() or spmScal...
Definition spm.c:1545
void spmIntConvert(spm_int_t n, const int *input, spm_int_t *output)
Convert integer array to spm_int_t format.
void spmScalMat(double alpha, const spmatrix_t *spm, spm_int_t n, void *A, spm_int_t lda)
Scale a matrix associated to a sparse matrix.
Definition spm.c:1602
void spmScalMatrix(double alpha, spmatrix_t *spm) __attribute__((__deprecated__("Please replace by spmScal() function (will be removed in 1.3.0)")))
Scale the spm.
Definition spm.c:1512
int spmReadDriverDist(spm_driver_t driver, const char *filename, spmatrix_t *spm, SPM_Comm comm)
Import a matrix file into an spm structure for a specific communicator.
int spmSave(const spmatrix_t *spm, const char *filename)
Save the spm structure into a file (internal format).
Definition spm_io.c:1065
int spmGenVec(spm_rhstype_t type, const spmatrix_t *spm, void *alpha, unsigned long long int seed, void *x, spm_int_t incx)
Generate a vector associated to a given matrix.
Definition spm.c:1802
double spmNorm(spm_normtype_t ntype, const spmatrix_t *spm)
Compute the norm of the spm.
Definition spm.c:514
void spm2Dense(const spmatrix_t *spm, void *A)
Convert the spm matrix into a dense matrix for test purpose.
Definition spm.c:450
void spmCopy(const spmatrix_t *spm_in, spmatrix_t *spm_out)
Create a copy of the spm.
Definition spm.c:969
void spmInit(spmatrix_t *spm)
Init the spm structure.
Definition spm.c:152
int spmGenMat(spm_rhstype_t type, spm_int_t nrhs, const spmatrix_t *spm, void *alpha, unsigned long long int seed, void *A, spm_int_t lda)
Generate a set of vectors associated to a given matrix.
Definition spm.c:1732
void spmScalVector(spm_coeftype_t flt, double alpha, spm_int_t n, void *A, spm_int_t lda) __attribute__((__deprecated__("Please replace by spmScalVec() or spmScalMat() depending on usage (will be removed in 1.3.0)")))
Scale a vector according to the spm type.
Definition spm.c:1665
void spmPrintInfo(const spmatrix_t *spm, FILE *f)
Print basic informations about the spm matrix into a given stream.
Definition spm.c:1026
The sparse matrix data structure.
Definition spm.h:64
int spmBlasSetNumThreadsOne(void)
Set the number of threads for blas calls (BLIS, MKL, OpenBLAS) to 1 and return the previous number of...
Definition spm.c:2334
static void s_spmPrintElt(FILE *f, spm_int_t i, spm_int_t j, float A)
Subroutines to print one element of an spm structure.
Definition spm.h:334
static void d_spmPrintElt(FILE *f, spm_int_t i, spm_int_t j, double A)
Subroutines to print one element of an spm structure.
Definition spm.h:325
int spmBlasGetNumThreads(void)
Return the current number of threads used for blas calls.
Definition spm.c:2280
int spmBlasSetNumThreads(int nt)
Set the number of threads for blas calls (BLIS, MKL, OpenBLAS) and return the previous number of blas...
Definition spm.c:2308
static void c_spmPrintElt(FILE *f, spm_int_t i, spm_int_t j, spm_complex32_t A)
Subroutines to print one element of an spm structure.
Definition spm.h:316