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 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
|
//------------------------------------------------------------------------------
// gb_mxcell_to_index: convert cell array to index list I or colon expression
//------------------------------------------------------------------------------
// SuiteSparse:GraphBLAS, Timothy A. Davis, (c) 2017-2022, All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
//------------------------------------------------------------------------------
// Get a list of indices from a built-in cell array.
// I is a cell array. I contains 0, 1, 2, or 3 items:
//
// 0: { } This is the built-in ':', like C(:,J), refering to all m
// rows, if C is m-by-n.
// 1: { list } A 1D list of row indices, like C(I,J).
// 2: { start,fini } start and fini are scalars (either double, int64,
// or uint64). This defines I = start:fini in colon
// notation.
// 3: { start,inc,fini } start, inc, and fini are scalars (double, int64,
// or uint64). This defines I = start:inc:fini in colon
// notation.
#include "gb_interface.h"
GrB_Index *gb_mxcell_to_index // return index list I
(
const mxArray *I_cell, // built-in cell array
base_enum_t base, // I is one-based or zero-based
const GrB_Index n, // dimension of matrix being indexed
bool *I_allocated, // true if output array I is allocated
GrB_Index *ni, // length (I)
int64_t *I_max // max (I) is computed if I_max is not NULL.
// I_max is 0-based.
)
{
//--------------------------------------------------------------------------
// check inputs
//--------------------------------------------------------------------------
CHECK_ERROR (I_cell == NULL || !mxIsCell (I_cell), "internal error 6") ;
//--------------------------------------------------------------------------
// get the contents of I_cell
//--------------------------------------------------------------------------
int len = mxGetNumberOfElements (I_cell) ;
CHECK_ERROR (len > 3, "index must be a cell array of length 0 to 3") ;
bool Item_allocated [3] = { false, false, false } ;
int64_t Item_len [3] = { 0, 0, 0 } ;
int64_t Item_max [3] = { -1, -1, -1 } ;
GrB_Index *Item [3] = { NULL, NULL, NULL } ;
for (int k = 0 ; k < len ; k++)
{
// convert I_cell {k} content to an integer list
Item [k] = (GrB_Index *) gb_mxarray_to_list (mxGetCell (I_cell, k),
base, &Item_allocated [k], &Item_len [k], &Item_max [k]) ;
}
//--------------------------------------------------------------------------
// parse the lists in the cell array
//--------------------------------------------------------------------------
GrB_Index *I ;
if (len == 0)
{
//----------------------------------------------------------------------
// I = { }
//----------------------------------------------------------------------
(*ni) = n ;
(*I_allocated) = false ;
I = (GrB_Index *) GrB_ALL ;
if (I_max != NULL)
{
// I_max is the last index in the matrix, based on its dimension.
(*I_max) = ((int64_t) n) - 1 ;
}
}
else if (len == 1)
{
//----------------------------------------------------------------------
// I = { list }
//----------------------------------------------------------------------
(*ni) = Item_len [0] ;
(*I_allocated) = Item_allocated [0] ;
I = (GrB_Index *) (Item [0]) ;
if (I_max != NULL)
{
// find the max entry in the list
if (Item_max [0] >= 0)
{
// the max entry has already been computed (1-based)
// convert from 1-based to 0-based
(*I_max) = Item_max [0] - 1 ;
}
else
{
// find the max entry (0-based)
GrB_Index List_max = 0 ;
GB_helper4 (I, (*ni), &List_max) ;
(*I_max) = ((int64_t) List_max) - 1 ;
}
}
}
else if (len == 2)
{
//----------------------------------------------------------------------
// I = { start, fini }, defining start:fini
//----------------------------------------------------------------------
CHECK_ERROR (Item_len [0] != 1 || Item_len [1] != 1,
"start and fini must be scalars for start:fini") ;
I = mxMalloc (3 * sizeof (GrB_Index)) ;
(*I_allocated) = true ;
I [GxB_BEGIN] = Item [0][0] ;
I [GxB_END ] = Item [1][0] ;
I [GxB_INC ] = 0 ; // unused
if (Item_allocated [0]) gb_mxfree ((void **) (& (Item [0]))) ;
if (Item_allocated [1]) gb_mxfree ((void **) (& (Item [1]))) ;
(*ni) = GxB_RANGE ;
if (I_max != NULL)
{
// find the last index in the start:fini list
(*I_max) = (int64_t) I [GxB_END] ;
}
}
else // if (len == 3)
{
//----------------------------------------------------------------------
// I = { start, inc, fini }, defining start:inc:fini
//----------------------------------------------------------------------
CHECK_ERROR (Item_len [0] != 1 || Item_len [1] != 1 ||
Item_len [2] != 1,
"start, inc, and fini must be scalars for start:inc:fini") ;
I = mxMalloc (3 * sizeof (GrB_Index)) ;
(*I_allocated) = true ;
I [GxB_BEGIN] = Item [0][0] ;
I [GxB_END ] = Item [2][0] ;
I [GxB_INC ] = 0 ;
int64_t iinc = Item [1][0] ;
if (Item_allocated [1])
{
// the 2nd item in the list is iinc, and if it was passed in as
// 1-based, it has been decremented. So increment it to get back
// to the correct value.
iinc++ ;
}
if (Item_allocated [0]) gb_mxfree ((void **) (& (Item [0]))) ;
if (Item_allocated [1]) gb_mxfree ((void **) (& (Item [1]))) ;
if (Item_allocated [2]) gb_mxfree ((void **) (& (Item [2]))) ;
if (iinc < 0)
{
I [GxB_INC] = (GrB_Index) (-iinc) ;
(*ni) = GxB_BACKWARDS ;
if (I_max != NULL)
{
// find the first entry in the list ibegin:iinc:iend.
(*I_max) = -1 ;
int64_t ibegin = (int64_t) I [GxB_BEGIN] ;
int64_t iend = (int64_t) I [GxB_END] ;
if (iinc != 0 && ibegin >= iend)
{
// the list is non-empty, for example, 7:-2:4 = [7 5]
// I_max = GB_ijlist (NULL, 0, GB_STRIDE, I)
(*I_max) = ibegin ;
}
}
}
else
{
I [GxB_INC] = (GrB_Index) (iinc) ;
(*ni) = GxB_STRIDE ;
if (I_max != NULL)
{
// find the last entry in the list ibegin:iinc:iend.
(*I_max) = -1 ;
int64_t ibegin = (int64_t) I [GxB_BEGIN] ;
int64_t iend = (int64_t) I [GxB_END] ;
if (iinc != 0 && ibegin <= iend)
{
// the list is non-empty, for example, 4:2:9 = [4 6 8]
// nI = length of the expanded list (see GB_ijproperties),
// which is 3 for the list 4:2:9.
int64_t nI = ((iend - ibegin) / iinc) + 1 ;
// I_max = GB_ijlist (NULL, nI-1, GB_STRIDE, I),
// which is 8 for the list 4:2:9
(*I_max) = ibegin + (nI-1) * iinc ;
}
}
}
}
return (I) ;
}
|