/* loops through 2D array in order of 3x3 submaps */ void UArray2_map_3x3_box(UArray2_T uarray2, void apply(int col, int row, UArray2_T a, void *elem, void *cl), void *cl) { int c, r; assert(uarray2); assert(apply); for (r = 0; r < UArray2_height(uarray2); r++) { for (c = 0; c < 3; c++) { apply(c, r, uarray2, UArray2_at(uarray2, c, r), cl); } } for (r = 0; r < UArray2_height(uarray2); r++) { for (c = 3; c < 6; c++) { apply(c, r, uarray2, UArray2_at(uarray2, c, r), cl); } } for (r = 0; r < UArray2_height(uarray2); r++) { for (c = 6; c < 9; c++) { apply(c, r, uarray2, UArray2_at(uarray2, c, r), cl); } } }
/* returns a void pointer to whatever is stored in location (i,j) in the * abstract 2D array */ void *UArray2b_at(T array2b, int i, int j) { assert(array2b); int x1, y1, x2, y2; UArray2_T *inner; x1 = i / array2b->blocksize; y1 = j / array2b->blocksize; x2 = i % array2b->blocksize; y2 = j % array2b->blocksize; inner = UArray2_at(array2b->shell, x1, y1);/* pointer to the block */ return UArray2_at(*inner, x2, y2); }
void check_and_print(int i, int j, UArray2_T a, void *p1, void *p2) { number *entry_p = p1; //number is a long - look at typedef *((bool *)p2) &= UArray2_at(a, i, j) == entry_p; if ( (i == (DIM1 -1) ) && (j == (DIM2 - 1) ) ) { /* we got the corner */ *((bool *)p2) &= (*entry_p == MARKER); } int elem = *(int *)UArray2_at(a, i, j); printf("%d, ", elem); printf("ar[%d,%d]\n", i, j); }
extern void *UArray2b_at(T array2b, int col, int row) { assert(col >= 0 && row >= 0); assert(array2b); int block_col = (col / array2b->blocksize); int block_row = (row / array2b->blocksize); int sub_col = (col % array2b->blocksize); int sub_row = (row % array2b->blocksize); UArray2_T array = *(UArray2_T *)UArray2_at(array2b->blockarray, block_col, block_row); return UArray2_at(array, sub_col, sub_row); }
void* UArray2b_at(T array2b, int i, int j) { assert(array2b); int blocksize = array2b->blocksize; UArray_T *temp = UArray2_at(array2b->blocks, i/blocksize, j/blocksize); UArray_T block = *temp; return UArray_at(block, blocksize * (i % blocksize) + (j % blocksize)); }
int main(int argc, char *argv[]) { (void)argc; (void)argv; UArray2_T test_array; bool OK = true; test_array = UArray2_new(DIM1, DIM2, ELEMENT_SIZE); //These functions check that the dimension has been set correctly OK &= (UArray2_width(test_array) == DIM1); OK &= (UArray2_height(test_array) == DIM2); OK &= (UArray2_size(test_array) == ELEMENT_SIZE); /* Note: we are only setting a value on the corner of the array */ *((number *)UArray2_at(test_array, DIM1-1, DIM2-1)) = MARKER; printf("Trying column major\n"); UArray2_map_col_major(test_array, check_and_print, &OK); printf("Trying row major\n"); UArray2_map_row_major(test_array, check_and_print, &OK); printf(" width = %d\n", UArray2_width(test_array)); printf("height %d\n", UArray2_height(test_array)); UArray2_free(&test_array); printf("The array is %sOK!\n", (OK ? "" : "NOT ")); }
//how to make sure we don't look through uncompleteed block void map_block(T array2b, UArray2_T uarray2, int c, int r, void apply(int col, int row, T array2b, void *elem, void *cl), void *cl) { int width, height; int blocked_width = array2b->blocksize * ceil(array2b->width/array2b->blocksize); int blocked_height = array2b->blocksize * ceil(array2b->height/array2b->blocksize); if((c * array2b->blocksize == blocked_width) && (array2b->width != blocked_width)) { width = array2b->width % array2b->blocksize;; } else { width = array2b->blocksize; } if((r * array2b->blocksize == blocked_height) && (array2b->height != blocked_height)) { height = array2b->height % array2b->blocksize; } else { height = array2b->blocksize; } for (int row = 0; row < height; row++) { for (int col = 0; col < width; col++) { int big_col = col + array2b->blocksize * c; int big_row = row + array2b->blocksize * r; apply(big_col, big_row, array2b, UArray2_at(uarray2, col, row), cl); } } }
/* apply function for the mapping through the UArray2 of pixels that have viedeo color values. The closure is a UArray2 with pixels that have RGB values */ void rgb_vc (int col, int row, UArray2_T uarray2, void *member, void *cl) { (void) uarray2; VideoColor_pixel ypbpr_pixel = member; Pnm_ppm pnm_image = cl; Pnm_rgb rgb_pixel = UArray2_at(pnm_image->pixels, col, row); unsigned denominator = pnm_image->denominator; float red = (float)rgb_pixel->red / (float)denominator ; float green = (float)rgb_pixel->green / (float)denominator ; float blue = (float)rgb_pixel->blue / (float)denominator ; ypbpr_pixel->y = (0.299 * red + 0.587 * green + 0.114 * blue); ypbpr_pixel->pb = (- 0.168736 * red - 0.331264 * green + 0.5 * blue); ypbpr_pixel->pr = (0.5 * red - 0.418688 * green - 0.081312 * blue); }
/* puts each pixel from reader into the 2D array in order */ UArray2_T pixels_to_array(Pnmrdr_T reader, Pnmrdr_mapdata data, FILE *fp) { unsigned pixel, area, i; int row = 0; int col = 0; unsigned *index; UArray2_T uarray2; uarray2 = UArray2_new(data.width, data.height, sizeof(unsigned)); area = data.width * data.height; /* puts each pixel in 2D array */ for (i = 0; i < area; i++) { pixel = Pnmrdr_get(reader); index = (unsigned *)UArray2_at(uarray2, col, row); *index = pixel; col++; /* at end of row, reset column to 0 */ if ((unsigned)col >= data.width) { col = 0; /* moves down 1 row */ row++; } } if (fp != NULL) { fclose(fp); } Pnmrdr_free(&reader); return uarray2; }
/* New blocked 2d array: blocksize = square root of # of cells in block */ extern T UArray2b_new (int width, int height, int size, int blocksize) { assert(width > 0 && height > 0); assert(size > 0 && blocksize > 0); T uarray2b = malloc(sizeof(*uarray2b)); /* Set given values */ uarray2b->width = width; uarray2b->height = height; uarray2b->size = size; uarray2b->blocksize = blocksize; /* Ceil up WidInBlocks to include partically filled blocks */ uarray2b->WidInBlocks = ceil((double) width/blocksize); uarray2b->HgtInBlocks = ceil((double) height/blocksize); /* Create outer UArray2 */ uarray2b->grid = UArray2_new(uarray2b->WidInBlocks, uarray2b->HgtInBlocks, size * blocksize * blocksize); /* Loop through outer UArray2, at each cell, create inner UArray2 * to store elements of a block */ for (int i = 0; i < uarray2b->WidInBlocks; i++) { for (int j = 0; j < uarray2b->HgtInBlocks; j++) { UArray2_T *temp = UArray2_at(uarray2b->grid, i, j); *temp = UArray2_new(blocksize, blocksize, size); } } return uarray2b; }
/* Return a pointer to the cell in column i, row j; * Index out of range is a checked run-time error */ extern void *UArray2b_at(T array2b, int col, int row) { assert(array2b); assert(col >= 0 && col < array2b->width); assert(row >= 0 && row < array2b->height); /* Coordinates in the outer UArray2 */ int blockcol = col / array2b->blocksize; int blockrow = row / array2b->blocksize; /* Coordinates in the inner UArray2 */ int colInBlock = col % array2b->blocksize; int rowInBlock = row % array2b->blocksize; /* Find inner UArray2 */ UArray2_T *temp = UArray2_at(array2b->grid, blockcol, blockrow); return UArray2_at(*temp, colInBlock, rowInBlock); }
void make_sub_arrays(T array2b, int big_width, int big_height) { UArray2_T *location ; for (int row = 0; row < big_height; row++) { for (int col = 0; col < big_width; col ++) { UArray2_T uarray2 = UArray2_new(array2b->blocksize, array2b->blocksize,array2b->size); location = UArray2_at(array2b->blockarray, col, row); *location = uarray2; } } }
void UArray2_map_col_major(T array2, void apply(void* elem, void* cl, int row, int col, T array), void* cl) { int j, i; for(j = 0; j < array2->width; j++) { for(i = 0; i < array2->height; i++) { apply((UArray2_at(array2, i, j)), cl, i, j, array2); } } }
/* box_check() * * Function is passed the upper right hand corner of one of the 3x3 subsections * of the sudoku puzzle and loops through each element of the section using the * frequency array to determine if there are any repeated elements. Calls a * helper function to perform the actual duplicate check. */ void box_check(UArray2_T array, int col, int row, UArray2_T freq_arr) { UArray2_map_row_major(freq_arr, reset_to_zero, NULL); for (int i = row; i < (row + 3); i++) { for (int j = col; j < (col + 3); j++) { int *curr_num = UArray2_at(array, j, i); assert(sizeof(*curr_num) == UArray2_size(array)); check_for_duplicate(array, freq_arr, (void *)curr_num); } } }
/*-----------------------------------------------------------------------------* | UArray2_map_row_major | Purpose: maps the given function onto every element of the given | UArray2 in row major order | Arguments: a pointer to the 2D array, a pointer to a void apply | function, the closure as a void * | Returns: - | Fail cases: | - the pointer to the 2D array is null | - the pointer to the apply function is null *-----------------------------------------------------------------------------*/ void UArray2_map_row_major(UArray2_T uarray2, void apply(int i, int j, UArray2_T uarray2, void *value, void *cl), void *cl) { assert(uarray2 != NULL); assert(apply != NULL); int i; int j; for (j = 0; j < UArray2_height(uarray2); j++) { for (i = 0; i < UArray2_width(uarray2); i++) { apply(i, j, uarray2, UArray2_at(uarray2, i, j), cl); }; }; }
void UArray2b_free(T *array2b) { assert(array2b && *array2b); T a2b = *array2b; int bwidth = UArray2_width(a2b->blocks); int bheight = UArray2_height(a2b->blocks); for (int i=0; i<bwidth; i++) { for (int j=0; j<bheight; j++) { UArray_free(UArray2_at(a2b->blocks,i,j)); } } UArray2_free(&(a2b->blocks)); free(*array2b); *array2b = NULL; }
/*-----------------------------------------------------------------------------* | UArray2_map_col_major | Purpose: maps the given function onto every element of the given | UArray2 in col major order | Arguments: a pointer to the 2D array, a pointer to a void apply | function, the closure as a void * | Returns: - | Fail cases: | - the pointer to the 2D array is null | - the pointer to the apply function is null *-----------------------------------------------------------------------------*/ void UArray2_map_col_major(UArray2_T uarray2, void apply(int i, int j, UArray2_T uarray2, void *value, void *cl), void *cl) { assert(uarray2 != NULL); assert(apply != NULL); int index; int i; int j; for (index = 0; index < UArray_length(uarray2->uarray); index ++) { i = get_i(index, UArray2_height(uarray2)); j = get_j(index, UArray2_height(uarray2)); apply(i, j, uarray2, UArray2_at(uarray2, i, j), cl); }; }
void check_and_print(int i, int j, UArray2_T a, void *p1, void *p2) { number *entry_p = p1; *((bool *)p2) &= UArray2_at(a, i, j) == entry_p; if ( (i == (DIM1 -1) ) && (j == (DIM2 - 1) ) ) { /* we got the corner */ *((bool *)p2) &= (*entry_p == MARKER); } printf("ar[%d,%d]\n", i, j); }
/* Free array2b */ extern void UArray2b_free (T *array2b) { assert(array2b && *array2b); /* Loop through outer UArray2 to free every inner UArray2 */ for (int i = 0; i < (*array2b)->WidInBlocks; i++) { for (int j = 0; j < (*array2b)->HgtInBlocks; j++) { UArray2_free(UArray2_at((*array2b)->grid, i, j)); } } /* Free outer UArray2 and the whole structure */ UArray2_free(&((*array2b)->grid)); FREE(*array2b); }
/* check_for_duplicate() * * Function takes the 2-Dimensional array containing the solution being checked, * the 9x1 frequency array and a pointer to the current element in the solution * puzzle being checked. Looks at index (current element - 1) of the frequency * array to determine if the current element has already been seen in the * current portion of the puzzle. Calls exit(1) if a duplicate is found. */ void check_for_duplicate(UArray2_T sol_arr, UArray2_T freq_arr, void *element) { int curr_num = *(int *)element; int *already_seen = NULL; already_seen = (int *)(UArray2_at(freq_arr, (curr_num - 1), 0)); assert(sizeof(*already_seen) == UArray2_size(sol_arr)); if (*already_seen == 0) { *already_seen = 1; } else { UArray2_free(&sol_arr); UArray2_free(&freq_arr); exit(1); } }
/* apply function for the mapping through the UArray2 of pixels that have RGB color values. The closure is a UArray2 with pixels that have video Color values */ void vc_rgb(int col, int row, UArray2_T uarray2, void *member, void *cl) { (void) uarray2; Pnm_rgb rgb_pixel = member; VideoColor_image vc_image = cl; VideoColor_pixel vc_pixel = UArray2_at(vc_image->pixels, col, row); float red = 1.0 * vc_pixel->y + 0.0 * vc_pixel->pb + 1.402 * vc_pixel->pr; float green = 1.0 * vc_pixel->y - 0.344136 * vc_pixel->pb - 0.714136 * vc_pixel->pr; float blue = 1.0 * vc_pixel->y + 1.772 * vc_pixel->pb + 0.0 * vc_pixel->pr; if (red < 0) { red = 0; } else if (red > 1){ red = 1; } if (green < 0) { green = 0; } else if (green > 1){ green = 1; } if (blue < 0) { blue = 0; } else if (blue > 1){ blue = 1; } unsigned red2 = (red * DENOMINATOR); unsigned green2 = (green * DENOMINATOR); unsigned blue2 = (blue * DENOMINATOR); rgb_pixel->red = red2; rgb_pixel->green = green2; rgb_pixel->blue = blue2; }
/* reads compressed image, wirtes PPM decompressed image */ extern void decompress40(FILE *input) { unsigned height, width; int read = fscanf(input, "COMP40 Compressed image format 2\n%u %u", &width, &height); assert(read == 2); int c = getc(input); assert(c == '\n'); Word_image w_image = Word_image_new( width/2, height/2); uint64_t temp = 0; uint64_t *temp2 = NULL; unsigned col, row; for (row = 0; row < (height/2); row++){ for (col = 0; col < (width/2); col++){ temp = Bitpack_newu(temp, 8, 0, getc(input)); temp = Bitpack_newu(temp, 8, 8, getc(input)); temp = Bitpack_newu(temp, 8, 16, getc(input)); temp = Bitpack_newu(temp, 8, 24, getc(input)); temp2 = UArray2_at(w_image->words, col, row); *temp2 = temp; } } WordFields_image wf_image2 = wordImage_to_wordFields (w_image); Word_image_free(&w_image); VideoColor_image vc_image_result = wordFields_to_videoColor (wf_image2); WordFields_image_free(&wf_image2); Pnm_ppm result = videoColor_to_pnm(vc_image_result); Pnm_ppmwrite(stdout, result); VideoColor_image_free(&vc_image_result); Pnm_ppmfree(&result); }
extern void UArray2b_map(T array2b, void apply(int col, int row, T array2b, void *elem, void *cl), void *cl) { assert(array2b); assert(apply); int block_width = ceil((float)array2b->width / (float)array2b->blocksize); int block_height = ceil((float)array2b->height / (float)array2b->blocksize); int col, row; for(row = 0; row < block_height; row++) { for (col = 0; col < block_width; col++) { map_block(array2b, *(UArray2_T *)UArray2_at(array2b->blockarray, col, row), col, row, apply, cl); } } }
void UArray2b_map(T array2b, void apply(), void* cl) { assert(array2b); int blocksize = array2b->blocksize; int max = blocksize * blocksize; int bheight = UArray2_height(array2b->blocks); int bwidth = UArray2_width(array2b->blocks); for(int blockj = 0; blockj < bheight; blockj++) { for(int blocki = 0; blocki < bwidth; blocki++) { UArray_T *temp = UArray2_at(array2b->blocks, blocki, blockj); for(int n = 0; n < max; n++) { /* n == blocksize * (i % blocksize) + (j % blocksize) n / blocksize == i % blocksize n % blocksize == j % blocksize */ int i = blocki*blocksize + n%blocksize; int j = blockj*blocksize + n/blocksize; if(i < array2b->width && j < array2b->height) apply(i, j, array2b, UArray_at(*temp, n), cl); } } } }
//create using a 2d array containing a T array of UArray2_T T UArray2b_new(int width, int height, int size, int blocksize) { T blockArray = malloc(sizeof(*blockArray)); blockArray->height = height; blockArray->width = width; blockArray->blocksize = blocksize; int bwidth = width/blocksize; if (width%blocksize != 0) bwidth++; int bheight = height/blocksize; if (height%blocksize != 0) bheight++; blockArray->blocks = UArray2_new(bwidth, bheight, sizeof(UArray_T)); for (int i=0; i<bwidth; i++) { for (int j=0; j<bheight; j++) { UArray_T *pblock = UArray2_at(blockArray->blocks, i, j); *pblock = UArray_new(blocksize*blocksize, size); } } return blockArray; }