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