1function gbtest29 2%GBTEST29 test subsref and subsasgn with logical indexing 3 4% SuiteSparse:GraphBLAS, Timothy A. Davis, (c) 2017-2021, All Rights Reserved. 5% SPDX-License-Identifier: GPL-3.0-or-later 6 7rng ('default') ; 8 9types = gbtest_types ; 10for k = 1:length (types) 11 type = types {k} ; 12 C = gbtest_cast (magic (3), type) ; 13 M = logical (C > 3) ; 14 A = gbtest_cast (2 * magic (3), type) ; 15 C (M) = A (M) ; 16 G = GrB (magic (3), type) ; 17 G (M) = A (M) ; 18 assert (gbtest_err (G, C) == 0) ; 19 if (isreal (C) && isreal (G)) 20 assert (gbtest_eq (G, C)) ; 21 else 22 assert (gbtest_eq (real (G), real (C))) ; 23 assert (gbtest_eq (imag (G), imag (C))) ; 24 end 25 26 C0 = GrB.random (3, 3, inf, 'range', GrB ([0 1], type)) ; 27 M = true (3) ; 28 A = GrB (1:9, type) ; 29 C1 = C0 ; 30 C1 (M) = A ; 31 C2 = double (C0) ; 32 C2 (M) = double (A) ; 33 assert (isequal (double (C1), C2)) ; 34 35 A = GrB (A, 'by row') ; 36 C1 = C0 ; 37 C1 (M) = A ; 38 assert (isequal (double (C1), C2)) ; 39 A = GrB (A', 'by row') ; 40 C1 = C0 ; 41 C1 (M) = A ; 42 assert (isequal (double (C1), C2)) ; 43end 44 45for trial = 1:40 46 fprintf ('.') 47 for m = 0:5 48 for n = 0:5 49 A = sprand (m, n, 0.5) ; 50 C = sprand (m, n, 0.5) ; 51 M = sprand (m, n, 0.5) ~= 0 ; 52 G = GrB (A) ; 53 54 x1 = A (M) ; 55 x2 = G (M) ; 56 57 % In MATLAB, if A and M are row vectors then A(M) is also a 58 % row vector. That contradicts this blog post: 59 % https://www.mathworks.com/company/newsletters/articles/matrix-indexing-in-matlab.html 60 % and also this documentation: 61 % https://www.mathworks.com/help/matlab/math/array-indexing.html 62 % Both those pages state that A(M) where M is a logical matrix 63 % always returns a column vector. GraphBLAS always returns a 64 % column vector. So x1(:) and x2(:) are compared below: 65 assert (gbtest_eq (x1 (:), x2 (:))) ; 66 67 % Both GraphBLAS and MATLAB can accept either row or column 68 % vectors x on input to C (M) = x. MATLAB treats this as 69 % C(M)=x(:), and so does GraphBLAS. So the subsasgn is in 70 % agreement between MATLAB and GraphBLAS, and all these uses 71 % work: 72 73 C1 = C ; 74 C1 (M) = A (M) ;%#ok<*SPRIX> % C1(M) is MATLAB, A(M) is MATLAB 75 76 C2 = GrB (C) ; 77 C2 (M) = A (M) ; % C2(M) is GrB, A(M) is MATLAB 78 79 C3 = GrB (C) ; 80 C3 (M) = G (M) ; % C3(M) is GrB, and G(M) is GrB 81 82 % this uses the MATLAB subasgn, after typecasting G(M) from 83 % class GrB to class double, using GrB/double: 84 85 C4 = C ; 86 C4 (M) = G (M) ; 87 88 assert (gbtest_eq (C1, C2)) ; 89 assert (gbtest_eq (C1, C3)) ; 90 assert (gbtest_eq (C1, C4)) ; 91 92 % also try with a GrB mask matrix M. In this case, A(M) where 93 % A is a MATLAB matrix and M is a GrB logical matrix fails. 94 % GrB/subsref can handle this case, but MATLAB doesn't call 95 % it. It tries using the built-in subsref instead, and it 96 % doesn't know what to do with a GrB logical matrix M. 97 98 M = GrB (M) ; 99 C5 = GrB (C) ; 100 C5 (M) = G (M) ; 101 102 assert (gbtest_eq (C1, C5)) ; 103 104 % test scalar assigment with logical indexing 105 K = logical (M) ; 106 C1 (K) = pi ; 107 C2 (M) = pi ; 108 C3 (M) = GrB (pi) ; 109 C4 (K) = GrB (pi) ; 110 C5 (M) = pi ; 111 112 assert (gbtest_eq (C1, C2)) ; 113 assert (gbtest_eq (C1, C3)) ; 114 assert (gbtest_eq (C1, C4)) ; 115 assert (gbtest_eq (C1, C5)) ; 116 117 end 118 end 119end 120 121fprintf ('\ngbtest29: all tests passed\n') ; 122 123