1function C = gb_random (varargin) 2%GB_RANDOM uniformly distributed random GraphBLAS matrix. 3% Implements C = GrB.random (...), C = sprand (...), C = sprand (...), 4 5% SuiteSparse:GraphBLAS, Timothy A. Davis, (c) 2017-2021, All Rights Reserved. 6% SPDX-License-Identifier: GPL-3.0-or-later 7 8%--------------------------------------------------------------------------- 9% parse inputs 10%--------------------------------------------------------------------------- 11 12% defaults 13dist = 'uniform' ; 14type = 'double' ; 15range = [ ] ; 16sym_option = 'unsymmetric' ; 17firstchar = nargin + 1 ; 18 19% look for strings 20for k = 1:nargin 21 arg = varargin {k} ; 22 if (ischar (arg)) 23 arg = lower (arg) ; 24 firstchar = min (firstchar, k) ; 25 switch arg 26 case { 'uniform', 'normal' } 27 dist = arg ; 28 case { 'range' } 29 range = varargin {k+1} ; 30 if (isobject (range)) 31 range = range.opaque ; 32 end 33 [rm, rn, type] = gbsize (range) ; 34 if (rm*rn > 2) 35 error ('range must contain at most 2 entries') ; 36 end 37 range = gbfull (range, type, 0, struct ('kind', 'full')) ; 38 case { 'unsymmetric', 'symmetric', 'hermitian' } 39 sym_option = arg ; 40 otherwise 41 error ('unknown option') ; 42 end 43 end 44end 45 46symmetric = isequal (sym_option, 'symmetric') ; 47hermitian = isequal (sym_option, 'hermitian') ; 48desc.base = 'zero-based' ; 49 50%--------------------------------------------------------------------------- 51% construct the pattern 52%--------------------------------------------------------------------------- 53 54if (firstchar == 2) 55 56 % C = GrB.random (A, ...) ; 57 A = varargin {1} ; 58 if (isobject (A)) 59 A = A.opaque ; 60 end 61 [m, n] = gbsize (A) ; 62 if ((symmetric || hermitian) && (m ~= n)) 63 error ('input matrix must be square') ; 64 end 65 [I, J] = gbextracttuples (A, desc) ; 66 e = length (I) ; 67 68elseif (firstchar == (4 - (symmetric || hermitian))) 69 70 % C = GrB.random (m, n, d, ...) 71 % C = GrB.random (n, d, ... 'symmetric') 72 % C = GrB.random (n, d, ... 'hermitian') 73 m = gb_get_scalar (varargin {1}) ; 74 if (symmetric || hermitian) 75 n = m ; 76 d = gb_get_scalar (varargin {2}) ; 77 else 78 n = gb_get_scalar (varargin {2}) ; 79 d = gb_get_scalar (varargin {3}) ; 80 end 81 if (isinf (d)) 82 % construct a full random matrix 83 e = m * n ; 84 I = repmat ((int64 (0) : int64 (m-1)), 1, n) ; 85 J = repmat ((int64 (0) : int64 (n-1)), m, 1) ; 86 else 87 % construct a sparse random matrix with about e entries 88 e = round (m * n * d) ; 89 I = int64 (floor (rand (e, 1) * m)) ; 90 J = int64 (floor (rand (e, 1) * n)) ; 91 end 92 93else 94 95 error ('invalid usage') ; 96 97end 98 99%--------------------------------------------------------------------------- 100% construct the values 101%--------------------------------------------------------------------------- 102 103if (isequal (type, 'logical')) 104 105 % X is logical: just pass a single logical 'true' to GrB.build 106 X = true ; 107 108else 109 110 % construct the initial random values 111 if (isequal (dist, 'uniform')) 112 X = rand (e, 1) ; 113 else 114 X = randn (e, 1) ; 115 end 116 117 % scale the values and typecast if requested 118 if (~isempty (range)) 119 lo = double (min (range)) ; 120 hi = double (max (range)) ; 121 if (contains (type, 'int')) 122 % X is signed or unsigned integer 123 X = cast (floor ((hi - lo + 1) * X + lo), type) ; 124 elseif (~contains (type, 'complex')) 125 % X is single or double real 126 X = cast ((hi - lo) * X + lo, type) ; 127 else 128 % X is complex: construct random imaginary values 129 if (isequal (dist, 'uniform')) 130 Y = rand (e, 1) ; 131 else 132 Y = randn (e, 1) ; 133 end 134 X = (hi - lo) * X + lo ; 135 Y = (hi - lo) * Y + lo ; 136 if (isequal (type, 'single complex')) 137 % X is single complex 138 X = single (X) ; 139 Y = single (Y) ; 140 end 141 X = complex (X, Y) ; 142 end 143 end 144 145end 146 147%--------------------------------------------------------------------------- 148% build the matrix 149%--------------------------------------------------------------------------- 150 151C = gbbuild (I, J, X, m, n, '2nd', desc) ; 152 153% make it symmetric or hermitian, if requested 154L = gbselect ('tril', C, -1) ; 155if (symmetric) 156 % C = tril (C) + tril (C,-1)' 157 C = gbeadd (gbselect ('tril', C, 0), '+', gbtrans (L)) ; 158elseif (hermitian) 159 % C = L + L' + real (diag (C)) 160 LT = gbtrans (L) ; 161 if (contains (gbtype (LT), 'complex')) 162 LT = gbapply ('conj', LT) ; 163 end 164 D = gbselect ('diag', C, 0) ; 165 if (contains (gbtype (D), 'complex')) 166 D = gbapply ('creal', D) ; 167 end 168 C = gbeadd (L, '+', gbeadd (LT, '+', D)) ; 169end 170 171