1 //------------------------------------------------------------------------------
2 // GrB_Matrix_reduce: reduce a matrix to a vector or scalar
3 //------------------------------------------------------------------------------
4 
5 // SuiteSparse:GraphBLAS, Timothy A. Davis, (c) 2017-2021, All Rights Reserved.
6 // SPDX-License-Identifier: Apache-2.0
7 
8 //------------------------------------------------------------------------------
9 // GrB_Matrix_reduce_TYPE: reduce a matrix to a scalar
10 //------------------------------------------------------------------------------
11 
12 // Reduce entries in a matrix to a scalar, c = accum (c, reduce_to_scalar(A)))
13 
14 // All entries in the matrix are "summed" to a single scalar t using the reduce
15 // monoid.  The result is either assigned to the output scalar c (if accum is
16 // NULL), or it accumulated in the result c via c = accum(c,t).  If A has no
17 // entries, the result t is the identity value of the monoid.  Unlike most
18 // other GraphBLAS operations, this operation uses an accum operator but no
19 // mask.
20 
21 #include "GB_reduce.h"
22 #include "GB_binop.h"
23 
24 #define GB_MATRIX_TO_SCALAR(prefix,type,T)                                     \
25 GrB_Info GB_EVAL3 (prefix, _Matrix_reduce_, T) /* c = accum (c, reduce (A)) */ \
26 (                                                                              \
27     type *c,                        /* result scalar                        */ \
28     const GrB_BinaryOp accum,       /* optional accum for c=accum(c,t)      */ \
29     const GrB_Monoid monoid,        /* monoid to do the reduction           */ \
30     const GrB_Matrix A,             /* matrix to reduce                     */ \
31     const GrB_Descriptor desc       /* descriptor (currently unused)        */ \
32 )                                                                              \
33 {                                                                              \
34     GB_WHERE1 ("GrB_Matrix_reduce_" GB_STR(T) " (&c, accum, monoid, A, desc)");\
35     GB_BURBLE_START ("GrB_reduce") ;                                           \
36     GB_RETURN_IF_NULL_OR_FAULTY (A) ;                                          \
37     GrB_Info info = GB_reduce_to_scalar (c, GB_EVAL3 (prefix, _, T), accum,    \
38         monoid, A, Context) ;                                                  \
39     GB_BURBLE_END ;                                                            \
40     return (info) ;                                                            \
41 }
42 
GB_MATRIX_TO_SCALAR(GrB,bool,BOOL)43 GB_MATRIX_TO_SCALAR (GrB, bool      , BOOL   )
44 GB_MATRIX_TO_SCALAR (GrB, int8_t    , INT8   )
45 GB_MATRIX_TO_SCALAR (GrB, int16_t   , INT16  )
46 GB_MATRIX_TO_SCALAR (GrB, int32_t   , INT32  )
47 GB_MATRIX_TO_SCALAR (GrB, int64_t   , INT64  )
48 GB_MATRIX_TO_SCALAR (GrB, uint8_t   , UINT8  )
49 GB_MATRIX_TO_SCALAR (GrB, uint16_t  , UINT16 )
50 GB_MATRIX_TO_SCALAR (GrB, uint32_t  , UINT32 )
51 GB_MATRIX_TO_SCALAR (GrB, uint64_t  , UINT64 )
52 GB_MATRIX_TO_SCALAR (GrB, float     , FP32   )
53 GB_MATRIX_TO_SCALAR (GrB, double    , FP64   )
54 GB_MATRIX_TO_SCALAR (GxB, GxB_FC32_t, FC32   )
55 GB_MATRIX_TO_SCALAR (GxB, GxB_FC64_t, FC64   )
56 
57 GrB_Info GrB_Matrix_reduce_UDT      // c = accum (c, reduce_to_scalar (A))
58 (
59     void *c,                        // result scalar
60     const GrB_BinaryOp accum,       // optional accum for c=accum(c,t)
61     const GrB_Monoid monoid,        // monoid to do the reduction
62     const GrB_Matrix A,             // matrix to reduce
63     const GrB_Descriptor desc       // descriptor (currently unused)
64 )
65 {
66     // Reduction to a user-defined type requires an assumption about the type
67     // of the scalar c.  It's just a void* pointer so its type must be
68     // inferred from the other arguments.  The type cannot be found from
69     // accum, since accum can be NULL.  The result is computed by the reduce
70     // monoid, and no typecasting can be done between user-defined types.
71     // Thus, the type of c must be the same as the reduce monoid.
72 
73     GB_WHERE1 ("GrB_Matrix_reduce_UDT (&c, accum, monoid, A, desc)") ;
74     GB_BURBLE_START ("GrB_reduce") ;
75     GB_RETURN_IF_NULL_OR_FAULTY (A) ;
76     GB_RETURN_IF_NULL_OR_FAULTY (monoid) ;
77     GrB_Info info = GB_reduce_to_scalar (c, monoid->op->ztype, accum,
78         monoid, A, Context) ;
79     GB_BURBLE_END ;
80     return (info) ;
81 }
82 
83 //------------------------------------------------------------------------------
84 // GrB_Matrix_reduce_Monoid: reduce a matrix to a vector via a monoid
85 //------------------------------------------------------------------------------
86 
GrB_Matrix_reduce_Monoid(GrB_Vector w,const GrB_Vector M,const GrB_BinaryOp accum,const GrB_Monoid monoid,const GrB_Matrix A,const GrB_Descriptor desc)87 GrB_Info GrB_Matrix_reduce_Monoid   // w<M> = accum (w,reduce(A))
88 (
89     GrB_Vector w,                   // input/output vector for results
90     const GrB_Vector M,             // optional mask for w, unused if NULL
91     const GrB_BinaryOp accum,       // optional accum for z=accum(w,t)
92     const GrB_Monoid monoid,        // reduce monoid for t=reduce(A)
93     const GrB_Matrix A,             // first input:  matrix A
94     const GrB_Descriptor desc       // descriptor for w, M, and A
95 )
96 {
97     GB_WHERE (w, "GrB_Matrix_reduce_Monoid (w, M, accum, monoid, A, desc)") ;
98     GB_BURBLE_START ("GrB_reduce") ;
99     GrB_Info info = GB_reduce_to_vector ((GrB_Matrix) w, (GrB_Matrix) M,
100         accum, monoid, A, desc, Context) ;
101     GB_BURBLE_END ;
102     return (info) ;
103 }
104 
105 //------------------------------------------------------------------------------
106 // GrB_Matrix_reduce_BinaryOp: reduce a matrix to a vector via a binary op
107 //------------------------------------------------------------------------------
108 
109 // Only binary ops that correspond to a known monoid are supported.
110 
GrB_Matrix_reduce_BinaryOp(GrB_Vector w,const GrB_Vector M,const GrB_BinaryOp accum,const GrB_BinaryOp op,const GrB_Matrix A,const GrB_Descriptor desc)111 GrB_Info GrB_Matrix_reduce_BinaryOp
112 (
113     GrB_Vector w,                   // input/output vector for results
114     const GrB_Vector M,             // optional mask for w, unused if NULL
115     const GrB_BinaryOp accum,       // optional accum for z=accum(w,t)
116     const GrB_BinaryOp op,          // reduce operator for t=reduce(A)
117     const GrB_Matrix A,             // first input:  matrix A
118     const GrB_Descriptor desc       // descriptor for w, M, and A
119 )
120 {
121     GB_WHERE (w, "GrB_Matrix_reduce_BinaryOp (w, M, accum, op, A, desc)") ;
122     GB_BURBLE_START ("GrB_reduce") ;
123 
124     //--------------------------------------------------------------------------
125     // check inputs
126     //--------------------------------------------------------------------------
127 
128     GB_RETURN_IF_NULL_OR_FAULTY (op) ;
129 
130     //--------------------------------------------------------------------------
131     // convert the binary op to its corresponding monoid
132     //--------------------------------------------------------------------------
133 
134     GrB_Monoid monoid = GB_binop_to_monoid (op) ;
135     if (monoid == NULL)
136     {
137         GB_ERROR (GrB_DOMAIN_MISMATCH, "Invalid binary operator:"
138             " z=%s(x,y) has no equivalent monoid\n", op->name) ;
139     }
140 
141     //--------------------------------------------------------------------------
142     // w<M> = reduce (A) via the monoid
143     //--------------------------------------------------------------------------
144 
145     GrB_Info info = GB_reduce_to_vector ((GrB_Matrix) w, (GrB_Matrix) M,
146         accum, monoid, A, desc, Context) ;
147     GB_BURBLE_END ;
148     return (info) ;
149 }
150 
151