/** * \brief Free the data pointed to by condemned of the given size. * * \param condemned Pointer to memory. * \param size Number of bytes. */ void m4ri_mmc_free(void *condemned, size_t size) { #ifdef __M4RI_ENABLE_MMC #if __M4RI_HAVE_OPENMP #pragma omp critical (mmc) { #endif static int j = 0; mmb_t *mm = m4ri_mmc_cache; if (size < __M4RI_MMC_THRESHOLD) { for(int i = 0; i < __M4RI_MMC_NBLOCKS; ++i) { if(mm[i].size == 0) { mm[i].size = size; mm[i].data = condemned; goto done; } } m4ri_mm_free(mm[j].data); mm[j].size = size; mm[j].data = condemned; j = (j+1) % __M4RI_MMC_NBLOCKS; } else { m4ri_mm_free(condemned); } done: ; #if __M4RI_HAVE_OPENMP } #endif // __M4RI_HAVE_OPENMP #else // __M4RI_ENABLE_MMC m4ri_mm_free(condemned); #endif // __M4RI_ENABLE_MMC }
void m4ri_destroy_all_codes() { int i; if (!codebook) { return; } for(i=1; i<MAXKAY+1; i++) { m4ri_mm_free(codebook[i]->inc); m4ri_mm_free(codebook[i]->ord); m4ri_mm_free(codebook[i]); } m4ri_mm_free(codebook); codebook = NULL; }
/** * \brief Cleans up memory block cache. * * This function is called automatically when the shared library is unloaded. * * \warning Not thread safe. */ void m4ri_mmc_cleanup(void) { #ifdef __M4RI_ENABLE_MMC #if __M4RI_HAVE_OPENMP #pragma omp critical (mmc) { #endif mmb_t *mm = m4ri_mmc_cache; for(int i = 0; i < __M4RI_MMC_NBLOCKS; ++i) { if (mm[i].size) m4ri_mm_free(mm[i].data); mm[i].size = 0; } #if __M4RI_HAVE_OPENMP } #endif // __M4RI_HAVE_OPENMP #endif // __M4RI_ENABLE_MMC }
void mzp_free_window(mzp_t* condemned){ m4ri_mm_free(condemned); }
void mzp_free(mzp_t *P) { m4ri_mm_free(P->values); m4ri_mm_free(P); }
/** * Implements both apply_p_right and apply_p_right_trans. */ void _mzd_apply_p_right_even(mzd_t *A, mzp_t *P, size_t start_row, size_t start_col, int notrans) { assert(A->offset == 0); if(A->nrows - start_row == 0) return; const size_t length = MIN(P->length,A->ncols); const size_t width = A->width; size_t step_size = MIN(A->nrows-start_row, MAX((CPU_L1_CACHE>>3)/A->width,1)); /* our temporary where we store the columns we want to swap around */ mzd_t *B = mzd_init(step_size, A->ncols); word *Arow; word *Brow; /* setup mathematical permutation */ size_t *permutation = (size_t *)m4ri_mm_calloc(sizeof(size_t),A->ncols); for(size_t i=0; i<A->ncols; i++) permutation[i] = i; if (!notrans) { for(size_t i=start_col; i<length; i++) { size_t t = permutation[i]; permutation[i] = permutation[P->values[i]]; permutation[P->values[i]] = t; } } else { for(size_t i=start_col; i<length; i++) { size_t t = permutation[length-i-1]; permutation[length-i-1] = permutation[P->values[length-i-1]]; permutation[P->values[length-i-1]] = t; } } /* we have a bitmask to encode where to write to */ word *write_mask = (word*)m4ri_mm_calloc(sizeof(word), length); for(size_t i=0; i<A->ncols; i+=RADIX) { const size_t todo = MIN(RADIX,A->ncols-i); for(size_t k=0; k<todo; k++) { if(permutation[i+k] == i+k) { write_mask[i/RADIX] |= ONE<<(RADIX - k - 1); } } } for(size_t i=start_row; i<A->nrows; i+=step_size) { step_size = MIN(step_size, A->nrows-i); for(size_t k=0; k<step_size; k++) { Arow = A->rows[i+k]; Brow = B->rows[k]; /*copy row & clear those values which will be overwritten */ for(size_t j=0; j<width; j++) { Brow[j] = Arow[j]; Arow[j] = Arow[j] & write_mask[j]; } } /* here we actually write out the permutation */ mzd_write_col_to_rows_blockd(A, B, permutation, write_mask, i, i+step_size, length); } m4ri_mm_free(permutation); m4ri_mm_free(write_mask); mzd_free(B); }