1 //------------------------------------------------------------------------------
2 // GB_AxB_semiring_builtin: determine if semiring is built-in
3 //------------------------------------------------------------------------------
4
5 // SuiteSparse:GraphBLAS, Timothy A. Davis, (c) 2017-2021, All Rights Reserved.
6 // SPDX-License-Identifier: Apache-2.0
7
8 //------------------------------------------------------------------------------
9
10 // Determine if A*B uses a built-in semiring, and if so, determine the
11 // opcodes and type codes of the semiring.
12
13 // This function is not used by the CUDA jitified kernels, since they can
14 // typecast the entries in the matrices A and B to the types of x and y of the
15 // operator, as needed.
16
17 #include "GB_mxm.h"
18 #include "GB_binop.h"
19
GB_AxB_semiring_builtin(const GrB_Matrix A,const bool A_is_pattern,const GrB_Matrix B,const bool B_is_pattern,const GrB_Semiring semiring,const bool flipxy,GB_Opcode * mult_opcode,GB_Opcode * add_opcode,GB_Type_code * xcode,GB_Type_code * ycode,GB_Type_code * zcode)20 bool GB_AxB_semiring_builtin // true if semiring is builtin
21 (
22 // inputs:
23 const GrB_Matrix A,
24 const bool A_is_pattern, // true if only the pattern of A is used
25 const GrB_Matrix B,
26 const bool B_is_pattern, // true if only the pattern of B is used
27 const GrB_Semiring semiring, // semiring that defines C=A*B
28 const bool flipxy, // true if z=fmult(y,x), flipping x and y
29 // outputs:
30 GB_Opcode *mult_opcode, // multiply opcode
31 GB_Opcode *add_opcode, // add opcode
32 GB_Type_code *xcode, // type code for x input
33 GB_Type_code *ycode, // type code for y input
34 GB_Type_code *zcode // type code for z output
35 )
36 {
37
38 //--------------------------------------------------------------------------
39 // check inputs
40 //--------------------------------------------------------------------------
41
42 // A and B may be aliased
43
44 GrB_BinaryOp add = semiring->add->op ; // add operator
45 GrB_BinaryOp mult = semiring->multiply ; // multiply operator
46
47 // add is a monoid
48 ASSERT (add->xtype == add->ztype && add->ytype == add->ztype) ;
49 ASSERT (!GB_OP_IS_POSITIONAL (add)) ;
50
51 // in a semiring, the ztypes of add and mult are always the same:
52 ASSERT (add->ztype == mult->ztype) ;
53
54 // The conditions above are true for any semiring and any A and B, whether
55 // or not this function handles the semiring as hard-coded. Now return for
56 // cases this function does not handle.
57
58 (*mult_opcode) = GB_NOP_opcode ;
59 (*xcode) = GB_ignore_code ;
60 (*ycode) = GB_ignore_code ;
61 (*zcode) = GB_ignore_code ;
62
63 //--------------------------------------------------------------------------
64 // check the monoid
65 //--------------------------------------------------------------------------
66
67 (*add_opcode) = add->opcode ;
68 if (*add_opcode >= GB_USER_opcode)
69 {
70 // semiring has a user-defined add operator for its monoid
71 return (false) ;
72 }
73
74 //--------------------------------------------------------------------------
75 // rename redundant boolean monoids
76 //--------------------------------------------------------------------------
77
78 if (add->ztype->code == GB_BOOL_code)
79 {
80 // Only the LAND, LOR, LXOR, and EQ monoids remain if z is
81 // boolean. MIN, MAX, PLUS, and TIMES are renamed.
82 (*add_opcode) = GB_boolean_rename (*add_opcode) ;
83 }
84
85 //--------------------------------------------------------------------------
86 // check the multiply operator
87 //--------------------------------------------------------------------------
88
89 if (!GB_binop_builtin (A->type, A_is_pattern, B->type, B_is_pattern,
90 mult, flipxy, mult_opcode, xcode, ycode, zcode))
91 {
92 return (false) ;
93 }
94
95 //--------------------------------------------------------------------------
96 // rename to ANY_PAIR
97 //--------------------------------------------------------------------------
98
99 if ((*mult_opcode) == GB_PAIR_opcode)
100 {
101 if (((*add_opcode) == GB_EQ_opcode) ||
102 ((*add_opcode) == GB_LAND_opcode) ||
103 ((*add_opcode) == GB_LOR_opcode) ||
104 ((*add_opcode) == GB_MAX_opcode) ||
105 ((*add_opcode) == GB_MIN_opcode) ||
106 ((*add_opcode) == GB_TIMES_opcode))
107 // rename to ANY_PAIR
108 (*add_opcode) = GB_PAIR_opcode ;
109 }
110
111 return (true) ;
112 }
113
114