File: GB_Descriptor_get.c

package info (click to toggle)
suitesparse-graphblas 7.4.0%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 67,112 kB
  • sloc: ansic: 1,072,243; cpp: 8,081; sh: 512; makefile: 506; asm: 369; python: 125; awk: 10
file content (186 lines) | stat: -rw-r--r-- 7,842 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
//------------------------------------------------------------------------------
// GB_Descriptor_get: get the status of a descriptor
//------------------------------------------------------------------------------

// SuiteSparse:GraphBLAS, Timothy A. Davis, (c) 2017-2022, All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

//------------------------------------------------------------------------------

// A descriptor modifies the behavoir of a GraphBLAS operation.

// This function is called via the GB_GET_DESCRIPTOR(...) macro.

//  Descriptor field:           Descriptor value:

//  desc->out                   GxB_DEFAULT or GrB_REPLACE

//      GrB_REPLACE means that the output matrix C is cleared just
//      prior to writing results back into it, via C<M> = results.  This
//      descriptor does not affect how C is used to compute the results.  If
//      GxB_DEFAULT, then C is not cleared before doing C<M>=results.

//  desc->mask                  GxB_DEFAULT, GrB_COMP, GrB_STRUCTURE, or
//                              GrB_COMP + GrB_STRUCTURE

//      An optional 'write mask' defines how the results are to be written back
//      into C.  The boolean mask matrix M has the same size as C (M is
//      typecasted to boolean if it has another type).  If the M input to the
//      GraphBLAS method is NULL, then implicitly M(i,j)=1 for all i and j.
//      Let Z be the results to be written into C (the same dimension as C).
//      If desc->mask is GxB_DEFAULT, and M(i,j)=1, then C(i,j) is over-written
//      with Z(i,j).  Otherwise, if M(i,j)=0 C(i,j) is left unmodified (it
//      remains an implicit zero if it is so, or its value is unchanged if it
//      has one).  If desc->mask is GrB_COMP, then the use of M is negated:
//      M(i,j)=0 means that C(i,j) is overwritten with Z(i,j), and M(i,j)=1
//      means that C(i,j) is left unchanged.  If the value is GrB_STRUCTURE,
//      only the pattern is used; any entry present in the pattern has the
//      value M(i,j)=1, and entries not in the pattern have the value M(i,j)=0.
//      The GrB_COMP and GrB_STUCTURE options can be combined, as GrB_COMP +
//      GrB_STRUCTURE.

//      Writing results Z into C via the mask M is written as C<M>=Z in
//      GraphBLAS notation.

//      Note that it is the value of M(i,j) that determines how C(i,j) is
//      overwritten.  If the (i,j) entry is present in the M matrix data
//      structure but has a numerical value of zero, then it is the same as if
//      (i,j) is not present and thus implicitly zero.  Both mean 'M(i,j)=0'
//      in the description above of how the mask M works.

//  desc->in0 and desc->in1     GxB_DEFAULT or GrB_TRAN

//      A GrB_Matrix passed as an input parameter to GraphBLAS methods can
//      optionally transpose them prior to using them.  desc->in0 always refers
//      to the first input to the method, and desc->in1 always refers to the
//      second one.

//      If the value of this descriptor is GxB_DEFAULT, then the matrix is used
//      as-is.  Otherwise, it is transposed first.  That is, the results are
//      the same as if the transpose of the matrix was passed to the method.

//  desc->axb                   can be:

//      GxB_DEFAULT = 0         automatic selection
//      GxB_AxB_GUSTAVSON       gather-scatter saxpy method
//      GxB_AxB_HASH            hash-based saxpy method
//      GxB_AxB_SAXPY           saxpy: either Gustavson or hash
//      GxB_AxB_DOT             dot product

//  desc->do_sort               true or false (default is false) 

//  desc->nthreads_max          max # number of threads to use (auto if <= 0)
//  desc->chunk                 chunk size for threadds

//      These are copied from the GrB_Descriptor into the Context.

#include "GB.h"

GB_PUBLIC
GrB_Info GB_Descriptor_get      // get the contents of a descriptor
(
    const GrB_Descriptor desc,  // descriptor to query, may be NULL
    bool *C_replace,            // if true replace C before C<M>=Z
    bool *Mask_comp,            // if true use logical negation of M
    bool *Mask_struct,          // if true use the structure of M
    bool *In0_transpose,        // if true transpose first input
    bool *In1_transpose,        // if true transpose second input
    GrB_Desc_Value *AxB_method, // method for C=A*B
    int *do_sort,               // if nonzero, sort in GrB_mxm
    GB_Context Context
)
{

    //--------------------------------------------------------------------------
    // check inputs
    //--------------------------------------------------------------------------

    // desc may be null, but if not NULL it must be initialized
    GB_RETURN_IF_FAULTY (desc) ;
    ASSERT (Context != NULL) ;  // Context is always present

    //--------------------------------------------------------------------------
    // get the contents of the descriptor
    //--------------------------------------------------------------------------

    // default values if descriptor is NULL
    GrB_Desc_Value C_desc    = GxB_DEFAULT ;
    GrB_Desc_Value Mask_desc = GxB_DEFAULT ;
    GrB_Desc_Value In0_desc  = GxB_DEFAULT ;
    GrB_Desc_Value In1_desc  = GxB_DEFAULT ;
    GrB_Desc_Value AxB_desc  = GxB_DEFAULT ;
    int nthreads_desc        = GxB_DEFAULT ;
    double chunk_desc        = GxB_DEFAULT ;
    int do_sort_desc         = GxB_DEFAULT ;

    // non-defaults descriptor values
    if (desc != NULL)
    { 
        // get the contents
        C_desc    = desc->out ;   // DEFAULT or REPLACE
        Mask_desc = desc->mask ;  // DEFAULT, COMP, STRUCTURE, or COMP+STRUCTURE
        In0_desc  = desc->in0 ;   // DEFAULT or TRAN
        In1_desc  = desc->in1 ;   // DEFAULT or TRAN
        AxB_desc  = desc->axb ;   // DEFAULT, GUSTAVSON, HASH, or DOT
        do_sort_desc = desc->do_sort ;  // DEFAULT, or true (nonzero)

        // default is zero.  if descriptor->nthreads_max <= 0, GraphBLAS selects
        // automatically: any value between 1 and the global nthreads_max.  If
        // descriptor->nthreads_max > 0, then that defines the exact number of
        // threads to use in the current GraphBLAS operation.
        nthreads_desc = desc->nthreads_max ;
        chunk_desc = desc->chunk ;
    }

    // check for valid values of each descriptor field
    if (!(C_desc    == GxB_DEFAULT || C_desc    == GrB_REPLACE) ||
        !(Mask_desc == GxB_DEFAULT   || Mask_desc == GrB_COMP ||
          Mask_desc == GrB_STRUCTURE || Mask_desc == GrB_COMP+GrB_STRUCTURE) ||
        !(In0_desc  == GxB_DEFAULT || In0_desc  == GrB_TRAN) ||
        !(In1_desc  == GxB_DEFAULT || In1_desc  == GrB_TRAN) ||
        !(AxB_desc  == GxB_DEFAULT || AxB_desc  == GxB_AxB_GUSTAVSON ||
          AxB_desc  == GxB_AxB_DOT ||
          AxB_desc  == GxB_AxB_HASH || AxB_desc  == GxB_AxB_SAXPY))
    { 
        return (GrB_INVALID_OBJECT) ;
    }

    if (C_replace != NULL)
    { 
        *C_replace = (C_desc == GrB_REPLACE) ;
    }
    if (Mask_comp != NULL)
    { 
        *Mask_comp = (Mask_desc == GrB_COMP)
                  || (Mask_desc == GrB_COMP + GrB_STRUCTURE) ;
    }
    if (Mask_struct != NULL)
    { 
        *Mask_struct = (Mask_desc == GrB_STRUCTURE)
                    || (Mask_desc == GrB_STRUCTURE + GrB_COMP) ;
    }
    if (In0_transpose != NULL)
    { 
        *In0_transpose = (In0_desc == GrB_TRAN) ;
    }
    if (In1_transpose != NULL)
    { 
        *In1_transpose = (In1_desc == GrB_TRAN) ;
    }
    if (AxB_method != NULL)
    { 
        *AxB_method = AxB_desc ;
    }
    if (do_sort != NULL)
    { 
        *do_sort = do_sort_desc ;
    }

    // The number of threads is copied from the descriptor into the Context, so
    // it is available to any internal function that needs it.
    Context->nthreads_max = nthreads_desc ;
    Context->chunk = chunk_desc ;

    return (GrB_SUCCESS) ;
}