1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
|
function codegen_aop_method (binop, op, xtype)
%CODEGEN_AOP_METHOD create a function to compute C(:,:)+=A
%
% codegen_aop_method (binop, op, xtype)
% SuiteSparse:GraphBLAS, Timothy A. Davis, (c) 2017-2025, All Rights Reserved.
% SPDX-License-Identifier: Apache-2.0
% determine type of z, x, and y from xtype and binop
switch (binop)
case { 'eq', 'ne', 'gt', 'lt', 'ge', 'le' }
% GrB_LT_* and related operators are TxT -> bool
ztype = 'bool' ;
ytype = xtype ;
case { 'cmplx' }
% GxB_CMPLX_* are TxT -> (complex T)
if (isequal (xtype, 'float'))
ztype = 'GxB_FC32_t' ;
else
ztype = 'GxB_FC64_t' ;
end
ytype = xtype ;
case { 'bshift' }
% z = bitshift (x,y): y is always int8
ztype = xtype ;
ytype = 'int8_t' ;
otherwise
% all other operators: z, x, and y have the same type
ztype = xtype ;
ytype = xtype ;
end
if (~isequal (xtype, ztype) || isequal (binop, 'first'))
% the type of x and z must match, and the operator must not be 'first'
return
end
f = fopen ('control.m4', 'w') ;
fprintf (f, 'm4_divert(-1)\n') ;
% no code is generated for the ANY operator (SECOND is used in its place)
assert (~isequal (binop, 'any')) ;
[fname, unsigned, bits] = codegen_type (xtype) ;
codegen_type_enabled (f, fname) ;
name = sprintf ('%s_%s', binop, fname) ;
% function names
fprintf (f, 'm4_define(`_subassign_23'', `_subassign_23__%s'')\n', name) ;
fprintf (f, 'm4_define(`_subassign_22'', `_subassign_22__%s'')\n', name) ;
fprintf (f, 'm4_define(`GB_ztype'', `#define GB_Z_TYPE %s'')\n', ztype) ;
fprintf (f, 'm4_define(`GB_xtype'', `#define GB_X_TYPE %s'')\n', xtype) ;
fprintf (f, 'm4_define(`GB_ytype'', `#define GB_Y_TYPE %s'')\n', ytype) ;
fprintf (f, 'm4_define(`GB_ctype'', `#define GB_C_TYPE %s'')\n', ztype) ;
fprintf (f, 'm4_define(`GB_atype'', `#define GB_A_TYPE %s'')\n', ytype) ;
fprintf (f, 'm4_define(`GB_declarec'', `#define GB_DECLAREC(cwork) %s cwork'')\n', ztype) ;
%{
% C_dense_update: operators z=f(x,y) where ztype and xtype match, and binop is not 'first'
if (isequal (xtype, ztype) && ~isequal (binop, 'first'))
% enable C dense update
fprintf (f, 'm4_define(`if_C_dense_update'', `0'')\n') ;
else
% disable C dense update
fprintf (f, 'm4_define(`if_C_dense_update'', `-1'')\n') ;
end
%}
% to get an entry from A and cast to ywork (but no typecasting here)
if (isequal (binop, 'first') || isequal (binop, 'pair'))
% value of A is ignored for the FIRST, PAIR, and positional operators
gb_copy_aij_to_ywork = '' ;
fprintf (f, 'm4_define(`GB_declarey'', `#define GB_DECLAREY(ywork)'')\n') ;
else
gb_copy_aij_to_ywork = sprintf (' ywork = Ax [(A_iso) ? 0 : (pA)]') ;
fprintf (f, 'm4_define(`GB_declarey'', `#define GB_DECLAREY(ywork) %s ywork'')\n', ytype) ;
end
fprintf (f, 'm4_define(`GB_copy_aij_to_ywork'', `#define GB_COPY_aij_to_ywork(ywork,Ax,pA,A_iso)%s'')\n', gb_copy_aij_to_ywork) ;
% to copy a scalar into C (no typecasting)
fprintf (f, 'm4_define(`GB_copy_cwork_to_c'', `#define GB_COPY_cwork_to_C(Cx,pC,cwork,C_iso) Cx [pC] = cwork'')\n') ;
% to copy an entry from A to C (with typecasting)
if (isequal (ytype, 'GxB_FC32_t') && isequal (ztype, 'bool'))
a2c = '((GB_crealf (Ax [pA]) != 0) || (GB_cimagf (Ax [pA]) != 0))' ;
elseif (isequal (ytype, 'GxB_FC64_t') && isequal (ztype, 'bool'))
a2c = '((GB_creal (Ax [pA]) != 0) || (GB_cimag (Ax [pA]) != 0))' ;
elseif (isequal (ytype, 'float') && isequal (ztype, 'GxB_FC32_t'))
a2c = '(GJ_CMPLX32 (Ax [pA], 0))' ;
elseif (isequal (ytype, 'double') && isequal (ztype, 'GxB_FC64_t'))
a2c = '(GJ_CMPLX64 (Ax [pA], 0))' ;
elseif (isequal (ytype, xtype))
a2c = sprintf ('Ax [pA]') ;
else
% use ANSI C typecasting
a2c = sprintf ('((%s) Ax [pA])', ytype) ;
end
fprintf (f, 'm4_define(`GB_copy_aij_to_c'', `#define GB_COPY_aij_to_C(Cx,pC,Ax,pA,A_iso,cwork,C_iso) Cx [pC] = (A_iso) ? cwork : %s'')\n', a2c) ;
a2c = strrep (a2c, 'pA', 'A_iso ? 0 : (pA)') ;
fprintf (f, 'm4_define(`GB_copy_aij_to_cwork'', `#define GB_COPY_aij_to_cwork(cwork,Ax,pA,A_iso) cwork = %s'')\n', a2c) ;
% mask macro
if (isequal (xtype, 'GxB_FC32_t') || isequal (xtype, 'GxB_FC64_t'))
asize = sprintf ('sizeof (%s)', xtype) ;
fprintf (f, 'm4_define(`GB_ax_mask'', `#define GB_AX_MASK(Ax,pA,asize) GB_MCAST (Ax, pA, %s)'')\n', asize) ;
else
fprintf (f, 'm4_define(`GB_ax_mask'', `#define GB_AX_MASK(Ax,pA,asize) (Ax [pA] != 0)'')\n') ;
end
% type-specific idiv
if (~isempty (strfind (op, 'idiv')))
if (unsigned)
op = strrep (op, 'idiv', sprintf ('idiv_uint%d', bits)) ;
else
op = strrep (op, 'idiv', sprintf ('idiv_int%d', bits)) ;
end
end
% create the binary operator
op = strrep (op, 'xarg', 'x') ;
op = strrep (op, 'yarg', 'y') ;
fprintf (f, 'm4_define(`GB_accumop'', `#define GB_ACCUM_OP(z,x,y) z = %s'')\n', op) ;
% create the disable flag
disable = sprintf ('defined(GxB_NO_%s)', upper (binop)) ;
disable = [disable (sprintf (' || defined(GxB_NO_%s)', upper (fname)))] ;
disable = [disable (sprintf (' || defined(GxB_NO_%s_%s)', upper (binop), upper (fname)))] ;
if (isequal (ytype, 'GxB_FC32_t') && ...
(isequal (binop, 'first') || isequal (binop, 'second')))
% disable the FIRST_FC32 and SECOND_FC32 binary operators for
% MS Visual Studio 2019. These files trigger a bug in the compiler.
disable = [disable ' || GB_COMPILER_MSC_2019_OR_NEWER'] ;
end
fprintf (f, 'm4_define(`GB_disable'', `#if (%s)\n#define GB_DISABLE 1\n#else\n#define GB_DISABLE 0\n#endif\n'')\n', disable) ;
fprintf (f, 'm4_divert(0)\n') ;
fclose (f) ;
% construct the *.c file
cmd = sprintf ('cat control.m4 Generator/GB_aop.c | m4 -P | awk -f codegen_blank.awk > ../../FactoryKernels/GB_aop__%s.c', name) ;
fprintf ('.') ;
system (cmd) ;
% append to the *.h file
system ('cat control.m4 Generator/GB_aop.h | m4 -P | awk -f codegen_blank.awk | grep -v SPDX >> ../../FactoryKernels/GB_aop__include.h') ;
delete ('control.m4') ;
|