1 //------------------------------------------------------------------------------
2 // GB_BinaryOp_compatible: check binary operator for type compatibility
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 // check type compatibilty for C = op (A,B).  With typecasting: A is cast to
11 // op->xtype, B is cast to op->ytype, the operator is computed, and then the
12 // result of op->ztype is cast to C->type.
13 
14 #include "GB.h"
15 
GB_BinaryOp_compatible(const GrB_BinaryOp op,const GrB_Type ctype,const GrB_Type atype,const GrB_Type btype,const GB_Type_code bcode,GB_Context Context)16 GrB_Info GB_BinaryOp_compatible     // check for domain mismatch
17 (
18     const GrB_BinaryOp op,          // binary operator to check
19     const GrB_Type ctype,           // C must be compatible with op->ztype
20     const GrB_Type atype,           // A must be compatible with op->xtype
21     const GrB_Type btype,           // B must be compatible with op->ytype
22     const GB_Type_code bcode,       // B may not have a type, just a code
23     GB_Context Context
24 )
25 {
26 
27     //--------------------------------------------------------------------------
28     // check inputs
29     //--------------------------------------------------------------------------
30 
31     ASSERT (op != NULL) ;
32     // ctype and btype may be NULL, but atype is never NULL
33     ASSERT (atype != NULL) ;
34     ASSERT (bcode <= GB_UDT_code) ;
35     GB_Opcode opcode = op->opcode ;
36     bool op_is_pair_or_positional = (opcode == GB_PAIR_opcode)
37         || GB_OPCODE_IS_POSITIONAL (opcode) ;
38 
39     //--------------------------------------------------------------------------
40     // first input A is cast into the type of op->xtype
41     //--------------------------------------------------------------------------
42 
43     if (opcode == GB_SECOND_opcode || op_is_pair_or_positional)
44     {
45         // first input is unused, so A is always compatible
46         ;
47     }
48     else if (!GB_Type_compatible (atype, op->xtype))
49     {
50         GB_ERROR (GrB_DOMAIN_MISMATCH,
51             "Incompatible type for z=%s(x,y):\n"
52             "first input of type [%s]\n"
53             "cannot be typecast to x input of type [%s]",
54             op->name, atype->name, op->xtype->name) ;
55     }
56 
57     //--------------------------------------------------------------------------
58     // second input B is cast into the type of op->ytype
59     //--------------------------------------------------------------------------
60 
61     if (opcode == GB_FIRST_opcode || op_is_pair_or_positional)
62     {
63         // second input is unused, so B is always compatible
64         ;
65     }
66     else if (btype != NULL)
67     {
68         // B has a type
69         if (!GB_Type_compatible (btype, op->ytype))
70         {
71             GB_ERROR (GrB_DOMAIN_MISMATCH,
72                 "Incompatible type for z=%s(x,y):\n"
73                 "second input of type [%s]\n"
74                 "cannot be typecast to y input of type [%s]",
75                 op->name, btype->name, op->ytype->name) ;
76         }
77     }
78     else
79     {
80         // B has a just a type code, not a type
81         if (!GB_code_compatible (bcode, op->ytype->code))
82         {
83             GB_ERROR (GrB_DOMAIN_MISMATCH,
84                 "Incompatible type for z=%s(x,y):\n"
85                 "second input of type [%s]\n"
86                 "cannot be typecast to y input of type [%s]",
87                 op->name, GB_code_string (bcode), op->ytype->name) ;
88         }
89     }
90 
91     //--------------------------------------------------------------------------
92     // result of binary operator of op->ztype is cast to C
93     //--------------------------------------------------------------------------
94 
95     if (!GB_Type_compatible (ctype, op->ztype))
96     {
97         GB_ERROR (GrB_DOMAIN_MISMATCH,
98             "Incompatible type for z=%s(x,y):\n"
99             "operator output z of type [%s]\n"
100             "cannot be typecast to result of type [%s]",
101             op->name, op->ztype->name, ctype->name) ;
102     }
103 
104     return (GrB_SUCCESS) ;
105 }
106 
107