1function [multiply_op add_op identity ztype xtype ytype] = GB_spec_semiring (semiring)
2%GB_SPEC_SEMIRING create a semiring
3%
4% [multiply_op add_op identity ztype xtype ytype] = GB_spec_semiring (semiring)
5%
6% Given a semiring, extract the multiply operator, additive operator, additive
7% identity, and the ztype of z for z=multiply(...) and the monoid z=add(z,z).
8%
9% A semiring is a struct with 3 fields, each a string, with defaults used if
10% fields are not present.  None of the content of the semiring should be
11% a struct.
12%
13%   multiply    a string with the name of the 'multiply' binary operator
14%               (default is 'times').
15%
16%   add         a string with the name of the 'add' operator (default is 'plus')
17%
18%   class       the MATLAB class of the operators (default is 'double', unless
19%               the multiply operator is 'or', 'and, or 'xor').  Any logical or
20%               numeric class is supported, which are the same as the 11
21%               built-in GraphBLAS types:
22%               'logical' (boolean in GraphBLAS), 'int8', 'uint8', 'int16',
23%               'uint16', 'int32', 'uint32', 'int64', 'uint64', 'single' (FP43
24%               in GraphBLAS), 'double' (FP64 in GraphBLAS),
25%               'single complex', and 'double complex'
26
27% SuiteSparse:GraphBLAS, Timothy A. Davis, (c) 2017-2021, All Rights Reserved.
28% SPDX-License-Identifier: Apache-2.0
29
30% set the default semiring
31if (isempty (semiring))
32    semiring = struct ;
33end
34if (~isfield (semiring, 'multiply'))
35    semiring.multiply = 'times' ;
36end
37if (~isfield (semiring, 'add'))
38    semiring.add = 'plus' ;
39end
40if (~isfield (semiring, 'class'))
41    semiring.class = 'double' ;
42end
43
44% create the multiply operator.  No error checks; it will be checked later
45% and can be any valid GraphBLAS binary operator.
46[mult mult_optype ztype xtype ytype] = GB_spec_operator (semiring.multiply, semiring.class);
47multiply_op.opname =  mult ;
48multiply_op.optype = mult_optype ;
49
50if (isequal (ytype, 'none'))
51    error ('invalid multiply op') ;
52end
53
54% create the add operator
55[add_opname add_optype add_ztype add_xtype add_ytype] = GB_spec_operator (semiring.add, ztype) ;
56add_op.opname = add_opname ;
57add_op.optype = add_optype ;
58
59% get the identity of the add operator
60identity = GB_spec_identity (add_op) ;
61
62% make sure the monoid is valid
63if (~isequal (add_ztype, add_xtype) || ~isequal (add_ztype, add_xtype))
64    error ('invalid monoid') ;
65end
66
67switch (add_opname)
68    case { 'min', 'max', 'plus', 'times', 'any', ...
69        'or', 'and', 'xor', 'eq', ...
70        'lor', 'land', 'lxor', 'lnxor', ...
71        'bitor', 'bitand', 'bitxor', 'bitxnor', ...
72        'bor', 'band', 'bxor', 'bxnor' }
73        % valid monoid
74    otherwise
75        error ('invalid monoid') ;
76end
77
78% make sure the monoid matches the operator ztype
79if (~isequal (add_ztype, ztype))
80    error ('invalid monoid: must match ztype of multiplier') ;
81end
82
83%   semiring
84%   multiply_op
85%   add_op
86%   identity
87%   ztype
88%   xtype
89%   ytype
90
91% make sure the semiring is built-in
92try
93    GB_mex_semiring (semiring, 0) ;
94catch
95    error ('not builtin semiring: %s.%s.%s', add_opname, mult, xtype) ;
96end
97
98