void GB_free_memory ( void *p // pointer to allocated block of memory to free #ifdef GB_MALLOC_TRACKING , size_t nitems // number of items to free , size_t size_of_item // sizeof each item #endif ) { if (p != NULL) { #ifdef GB_MALLOC_TRACKING { // at least one item is always allocated nitems = GB_IMAX (1, nitems) ; int nmalloc = --GB_Global.nmalloc ; GB_Global.inuse -= nitems * size_of_item ; #ifdef GB_PRINT_MALLOC printf ("free: %14p %3d %1d n "GBd" size "GBd"\n", p, nmalloc, GB_Global.malloc_debug, (int64_t) nitems, (int64_t) size_of_item) ; if (nmalloc < 0) { printf ("%d free %p negative mallocs!\n", nmalloc, p) ; } #endif ASSERT (nmalloc >= 0) ; } #endif GB_FREE (p) ; } }
bool GB_to_nonhyper_test // test for conversion to hypersparse ( GrB_Matrix A, // matrix to test int64_t k, // # of non-empty vectors of A, an estimate is OK, // but normally A->nvec_nonempty int64_t vdim // normally A->vdim ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- ASSERT (A != NULL) ; //-------------------------------------------------------------------------- // test for conversion //-------------------------------------------------------------------------- if (!A->is_hyper) { //---------------------------------------------------------------------- // A is already non-hypersparse: no need to convert it //---------------------------------------------------------------------- return (false) ; } else { //---------------------------------------------------------------------- // A is hypersparse; test for conversion to non-hypersparse //---------------------------------------------------------------------- // get the vector dimension of this matrix float n = (float) vdim ; // get the hyper ratio for this matrix float r = A->hyper_ratio ; // ensure k is in the range 0 to n, inclusive k = GB_IMAX (k, 0) ; k = GB_IMIN (k, n) ; return (n <= 1 || (((float) k) > n * r * 2)) ; } }
GrB_Info GB_ijproperties // check I and determine its properties ( const GrB_Index *I, // list of indices, or special const int64_t ni, // length I, or special const int64_t nI, // actual length from GB_ijlength const int64_t limit, // I must be in the range 0 to limit-1 const int64_t Ikind, // kind of I, from GB_ijlength const int64_t Icolon [3], // begin:inc:end from GB_ijlength bool *I_is_unsorted, // true if I is out of order bool *I_is_contig, // true if I is a contiguous list, imin:imax int64_t *imin_result, // min (I) int64_t *imax_result, // max (I) bool is_I, // true if I, false if J (debug only) GB_Context Context ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- // limit: the matrix dimension (# of rows or # of columns) // ni: only used if Ikind is GB_LIST: the length of the array I // nI: the length of the list I, either actual or implicit // Ikind: GB_ALL, GB_RANGE, GB_STRIDE (both +/- inc), or GB_LIST // Icolon: begin:inc:end for all but GB_LIST // outputs: // I_is_unsorted: true if Ikind == GB_LIST and not in ascending order // I_is_contig: true if I has the form I = begin:end // imin, imax: min (I) and max (I), but only including actual indices // in the sequence. The end value of I=begin:inc:end may not be // reached. For example if I=1:2:10 then max(I)=9, not 10. ASSERT (I != NULL) ; ASSERT (limit >= 0) ; ASSERT (limit <= GB_INDEX_MAX) ; int64_t imin, imax ; //-------------------------------------------------------------------------- // scan I //-------------------------------------------------------------------------- // scan the list of indices: check if OK, determine if they are // jumbled, or contiguous, their min and max index, and actual length bool I_unsorted = false ; bool I_contig = true ; if (Ikind == GB_ALL) { //---------------------------------------------------------------------- // I = 0:limit-1 //---------------------------------------------------------------------- imin = 0 ; imax = limit-1 ; } else if (Ikind == GB_RANGE) { //---------------------------------------------------------------------- // I = imin:imax //---------------------------------------------------------------------- imin = Icolon [GxB_BEGIN] ; imax = Icolon [GxB_END ] ; if (imin > imax) { // imin > imax: list is empty imin = limit ; imax = -1 ; } else { // check the limits GB_ICHECK (imin, limit) ; GB_ICHECK (imax, limit) ; } } else if (Ikind == GB_STRIDE) { //---------------------------------------------------------------------- // I = imin:iinc:imax //---------------------------------------------------------------------- int64_t ibegin = Icolon [GxB_BEGIN] ; int64_t iinc = Icolon [GxB_INC ] ; int64_t iend = Icolon [GxB_END ] ; // if iinc == 1 on input, the kind has been changed to GB_RANGE ASSERT (iinc != 1) ; if (iinc == 0) { // stride is zero: list is empty, contiguous, and sorted imin = limit ; imax = -1 ; } else if (iinc > 0) { // stride is positive, get the first and last indices imin = GB_ijlist (I, 0, GB_STRIDE, Icolon) ; imax = GB_ijlist (I, nI-1, GB_STRIDE, Icolon) ; } else { // stride is negative, get the first and last indices imin = GB_ijlist (I, nI-1, GB_STRIDE, Icolon) ; imax = GB_ijlist (I, 0, GB_STRIDE, Icolon) ; } if (imin > imax) { // list is empty: so it is contiguous and sorted imin = limit ; imax = -1 ; } else { // list is contiguous if the stride is 1, not contiguous otherwise I_contig = false ; // check the limits GB_ICHECK (imin, limit) ; GB_ICHECK (imax, limit) ; } } else // Ikind == GB_LIST { //---------------------------------------------------------------------- // I is an array of indices //---------------------------------------------------------------------- // scan I to find imin and imax, and validate the list. Also determine // if it is sorted or not. imin = limit ; imax = -1 ; int64_t ilast = -1 ; for (int64_t inew = 0 ; inew < ni ; inew++) { int64_t i = I [inew] ; GB_ICHECK (i, limit) ; if (i < ilast) { // The list I of row indices is out of order, and C=A(I,J) will // need to use qsort to sort each column. If C=A(I,J)' is // computed, however, this flag will be set back to false, // since qsort is not needed if the result is transposed. I_unsorted = true ; } if (inew > 0 && i != ilast + 1) { I_contig = false ; } imin = GB_IMIN (imin, i) ; imax = GB_IMAX (imax, i) ; ilast = i ; } if (ni == 1) { // a single entry does not need to be sorted ASSERT (I [0] == imin && I [0] == imax && !I_unsorted) ; } if (ni == 0) { // the list is empty ASSERT (imin == limit && imax == -1) ; } } ASSERT (GB_IMPLIES (I_contig, !I_unsorted)) ; ASSERT (GB_IMPLIES (Ikind == GB_ALL, I_contig)) ; ASSERT (GB_IMPLIES (Ikind == GB_RANGE, I_contig)) ; // I_is_contig is true if the list of row indices is a contiguous list, // imin:imax in MATLAB notation. This is an important special case. // I_is_unsorted is true if I is an explicit list, the list is non-empty, // and the indices are not sorted in ascending order. (*I_is_contig) = I_contig ; (*I_is_unsorted) = I_unsorted ; (*imin_result) = imin ; (*imax_result) = imax ; return (GrB_SUCCESS) ; }
GrB_Info GB_Type_new ( GrB_Type *type, // handle of user type to create const size_t sizeof_ctype, // size of the user type const char *name // name of the type, as "sizeof (ctype)" ) { //-------------------------------------------------------------------------- // check inputs //-------------------------------------------------------------------------- GB_WHERE ("GrB_Type_new (&type, sizeof (ctype))") ; GB_RETURN_IF_NULL (type) ; (*type) = NULL ; //-------------------------------------------------------------------------- // create the type //-------------------------------------------------------------------------- // allocate the type GB_CALLOC_MEMORY (*type, 1, sizeof (struct GB_Type_opaque)) ; if (*type == NULL) { return (GB_NO_MEMORY) ; } // initialize the type GrB_Type t = *type ; t->magic = GB_MAGIC ; t->size = GB_IMAX (sizeof_ctype, 1) ; t->code = GB_UDT_code ; // run-time user-defined type //-------------------------------------------------------------------------- // get the name //-------------------------------------------------------------------------- // if no name found, a generic name is used instead strncpy (t->name, "user-type", GB_LEN-1) ; char input2 [GB_LEN+1] ; char *p = NULL ; // look for "sizeof" in the input string if (name != NULL) { strncpy (input2, name, GB_LEN) ; p = strstr (input2, "sizeof") ; } if (p != NULL) { // "sizeof" appears in the input string, advance past it p += 6 ; // find leading "(" if it appears, and advance to one character past it char *p2 = strstr (p, "(") ; if (p2 != NULL) p = p2 + 1 ; // find trailing ")" if it appears, and delete it p2 = strstr (p, ")") ; if (p2 != NULL) *p2 = '\0' ; // p now contains the final name, copy it to the output name strncpy (t->name, p, GB_LEN-1) ; } return (GrB_SUCCESS) ; }