1function c = GB_spec_reduce_to_scalar (cin, accum, reduce, A)
2%GB_SPEC_REDUCE_TO_SCALAR a MATLAB mimic of GrB_reduce (to scalar)
3%
4% Usage:
5% c = GB_spec_reduce_to_scalar (cin, accum, reduce, A)
6%
7% Reduces a matrix or vector to a scalar
8%
9% cin is a dense scalar
10
11% SuiteSparse:GraphBLAS, Timothy A. Davis, (c) 2017-2021, All Rights Reserved.
12% SPDX-License-Identifier: Apache-2.0
13
14%-------------------------------------------------------------------------------
15% get inputs
16%-------------------------------------------------------------------------------
17
18if (nargout > 1 || nargin ~= 4)
19    error ('usage: c = GB_spec_Matrix_reduce (cin, accum, reduce, A)') ;
20end
21
22if (isstruct (cin) || issparse (cin) || ~isscalar (cin))
23    error ('cin must be a dense scalar') ;
24end
25
26cin_type = GB_spec_type (cin) ;
27
28% get the type of A
29if (isstruct (A))
30    atype = A.class ;
31else
32    atype = GB_spec_type (A) ;
33end
34
35% get the reduce operator. default type is the type of A
36[reduce_op reduce_optype zt xt yt] = GB_spec_operator (reduce, atype) ;
37assert (isequal (zt, xt)) ;
38assert (isequal (zt, yt)) ;
39
40if (GB_spec_is_positional (reduce_op))
41    error ('reduce operator cannot be positional') ;
42end
43
44% get the identity
45identity = GB_spec_identity (reduce_op, reduce_optype) ;
46if (isempty (identity))
47    identity = 0 ;
48end
49
50% get the input matrix
51A = GB_spec_matrix (A, identity) ;
52
53% get the accumulator and its types for z = accum(x,y)
54[accum_op accum_optype ztype xtype ytype ] = GB_spec_operator (accum, cin_type) ;
55
56if (GB_spec_is_positional (accum_op))
57    error ('accum operator cannot be positional') ;
58end
59
60%-------------------------------------------------------------------------------
61% do the work via a clean MATLAB interpretation of the entire GraphBLAS spec
62%-------------------------------------------------------------------------------
63
64% cast A to the type of the reduce operator, but only entries in the pattern
65
66t = identity ;
67if (nnz (A.pattern) > 0)
68    X = GB_mex_cast (A.matrix (A.pattern), reduce_optype) ;
69    for k = 1:length (X)
70        t = GB_spec_op (reduce, t, X (k)) ;
71    end
72end
73
74% apply the accumulator.  no mask. t is a dense matrix so this is
75% different than GB_spec_accum.
76if (isempty (accum_op))
77    c = GB_mex_cast (t, cin_type) ;
78else
79    % c = cin "+" t, but typecast all the arguments
80    t   = GB_mex_cast (t,   xtype) ;     % cast t to accum xtype
81    cin = GB_mex_cast (cin, ytype) ;     % cast cin to accum ytype
82    z = GB_spec_op (accum, cin, t) ;     % z = accum (cin,t)
83    c = GB_mex_cast (z, cin_type) ;      % cast z to type of cin
84end
85
86