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