├── README ├── bucket-sort ├── bucket_sort.c └── bucket_sort_pipeline.c ├── goldberg-conjecture ├── Makefile └── goldberg.c ├── image-manip ├── image_manip.c └── image_manip_serial.c ├── integration └── integration.c ├── mandelbrot ├── Makefile ├── mandel_bitmap.c └── mandelbrot.c ├── matrix-multipy ├── Makefile ├── README ├── main.c ├── test-solaris.sh └── test.sh ├── metal-plate ├── metal_plate.c ├── metal_plate_modified.c └── pthread_metal_plate.c ├── moores-algorithm ├── ipc_moore.c ├── pthread_moore.c └── semaphore.h ├── nbody └── nbody.c ├── newton-type-optimization ├── Makefile ├── main.cxx ├── matrix.cxx └── minimize.cxx └── prefix-sum └── prefix_sum.c /README: -------------------------------------------------------------------------------- 1 | These are just examples that I used for learning. They are not production quality codes, just use them for reference. 2 | -------------------------------------------------------------------------------- /bucket-sort/bucket_sort.c: -------------------------------------------------------------------------------- 1 | /* File: bucket_sort.c 2 | Author: Jharrod LaFon 3 | Date: Spring 2011 4 | Purpose: Parallel implementation of bucket sort 5 | */ 6 | #include "memwatch.h" 7 | #include 8 | #include 9 | //#include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #define DEFAULT_ARRAY_SIZE 10 15 | #define MAX_NUM_SIZE 100 16 | 17 | /* Struct to hold configuration options */ 18 | typedef struct 19 | { 20 | int rank,size, array_size,slice,max_num,verbose, print_array, print_ranges; 21 | } Params; 22 | 23 | /* Struct defining a bucket, that contains index items */ 24 | typedef struct 25 | { 26 | int * array; 27 | int index; 28 | } Bucket; 29 | 30 | /* Inserts x into the bucket, and updates the index */ 31 | void bucket_insert(Bucket * b, int x) 32 | { 33 | b->array[b->index] = x; 34 | b->index = b->index +1; 35 | } 36 | 37 | /* Function to compare two values for sorting, needed for quick sort */ 38 | int compare( const void * n1, const void * n2) 39 | { 40 | return (*(int*)n1 - *(int*)n2); 41 | } 42 | 43 | /* Checks a bucket for sortedness */ 44 | int check_bucket(Bucket * b) 45 | { 46 | int i, last = b->array[0]; 47 | for(i = 0; i < b->index; i++) 48 | { 49 | if(b->array[i] < last) 50 | return -1; 51 | last = b->array[i]; 52 | } 53 | return 0; 54 | } 55 | 56 | /* Function to be executed by the workers */ 57 | void slave(Params * p) 58 | { 59 | /* Timer */ 60 | double start, end; 61 | 62 | /* Loop Counter */ 63 | int i; 64 | 65 | /* Number of large buckets, also the number of ranks */ 66 | int num_buckets = p->size; 67 | 68 | /* Size of one large bucket, that is the array size/(number of ranks) */ 69 | int large_bucket_size = ceil(p->array_size/(float)p->size); 70 | 71 | /* Size of small bucket size, that is a large bucket divided by the number of ranks */ 72 | int small_bucket_size = large_bucket_size; 73 | 74 | /* Pointer to the resulting array, only malloc'd by the master rank */ 75 | int * array; 76 | 77 | /* To be executed by the master rank only, sets up the large array to be scattered */ 78 | if(p->rank == 0) 79 | { 80 | /* Start Timer */ 81 | start = MPI_Wtime(); 82 | 83 | /* Master array */ 84 | array = (int *) malloc(sizeof(int)*p->array_size); 85 | 86 | /* Seed the random number generator */ 87 | srand(time(NULL)); 88 | 89 | /* Initialize array with random numbers, from 0 to max_num */ 90 | for(i = 0; i < p->array_size; i++) 91 | array[i] = rand()%(p->max_num); 92 | if(p->print_array) 93 | for(i = 0; i < p->array_size; i++) 94 | fprintf(stderr,"Array[%d] = %d\n",i,array[i]); 95 | 96 | 97 | /* Print problem parameters if the user wants */ 98 | if(p->verbose) 99 | fprintf(stdout,"Number of buckets: %d\n\ 100 | Large bucket size:\t%d\n\ 101 | Small bucket size:\t%d\n\ 102 | Array size:\t\t%d\n\ 103 | Largest number:\t%d\n",num_buckets,large_bucket_size,small_bucket_size,p->array_size,p->max_num); 104 | } 105 | 106 | /* Array of small buckets. 107 | If the number of ranks is P, each rank has P smaller buckets. */ 108 | Bucket ** buckets = (Bucket **) malloc(sizeof(Bucket*)*num_buckets); 109 | for(i = 0; i < num_buckets; i++) 110 | { 111 | /* Malloc pointer to the bucket */ 112 | buckets[i] = (Bucket *) malloc(sizeof(Bucket)); 113 | /* Malloc pointer to the bucket's array */ 114 | buckets[i]->array = (int*) malloc(sizeof(int)*small_bucket_size*2.0); 115 | /* Index points to the next location to insert an element */ 116 | buckets[i]->index = 0; 117 | } 118 | 119 | /* Large bucket to hold numbers from the initial scatter. */ 120 | Bucket large_bucket; 121 | 122 | /* NOTE: The overestimation of bucket sizes is due to rand() not producing a true uniform distribution. 123 | If the numbers are not uniformly distributed, some buckets will be larger than others. */ 124 | int * my_bucket_array = (int*) malloc(sizeof(int)*large_bucket_size*4.0); 125 | large_bucket.array = my_bucket_array; 126 | large_bucket.index = 0; 127 | 128 | /* Print range of each bucket */ 129 | int range_min = (p->max_num*p->rank)/p->size, range_max = (p->max_num*(p->rank+1))/p->size; 130 | 131 | if(p->print_ranges) 132 | fprintf(stderr,"Bucket [%d] %d => %d\n",p->rank,range_min,range_max); 133 | 134 | /* Scatter array into large buckets */ 135 | MPI_Scatter(array,large_bucket_size,MPI_INT,large_bucket.array,large_bucket_size,MPI_INT,0,MPI_COMM_WORLD); 136 | int dest; 137 | /* Place numbers from large bucket into small buckets */ 138 | for(i = 0; i < large_bucket_size; i++) 139 | { 140 | /* Calculate the destination bucket by mapping a number from 0 to max_num to 141 | a bucket from 0 to num_buckets */ 142 | dest = (large_bucket.array[i] * num_buckets)/p->max_num; 143 | /* If the destination is to my bucket, then insert it into my local bucket directly */ 144 | if(dest == p->rank) 145 | bucket_insert(&large_bucket,large_bucket.array[i]); 146 | /* Otherwise insert the number into someone else bucket */ 147 | else 148 | bucket_insert(buckets[dest],large_bucket.array[i]); 149 | } 150 | MPI_Request * requests = (MPI_Request *) malloc(sizeof(MPI_Request) * p->size); 151 | /* Send each bucket to it's owner, non blocking so that there is no deadlock */ 152 | for(i = 0; i < p->size; i++) 153 | /* Make sure I'm not sending to myself */ 154 | if(i != p->rank) 155 | MPI_Isend(buckets[i]->array,small_bucket_size*2,MPI_INT,i,buckets[i]->index,MPI_COMM_WORLD,&requests[i]); 156 | MPI_Status status; 157 | /* Current is the location at which to begin inserting elements into my large bucket. 158 | My large bucket already contains my numbers, so begin there */ 159 | int current = large_bucket.index; 160 | /* Receive small buckets from other ranks */ 161 | for(i = 0; i < p->size-1; i++) 162 | { 163 | MPI_Recv(&large_bucket.array[current],small_bucket_size*2,MPI_INT,MPI_ANY_SOURCE,MPI_ANY_TAG,MPI_COMM_WORLD,&status); 164 | if(p->verbose) 165 | fprintf(stderr,"[%d] Received %d elements from %d total now %d\n",p->rank, status.MPI_TAG, status.MPI_SOURCE,current+status.MPI_TAG); 166 | current+=status.MPI_TAG; 167 | } 168 | large_bucket.index = current; 169 | 170 | /* Sort my bucket */ 171 | qsort(&large_bucket.array[0],current,sizeof(int),compare); 172 | 173 | /* Gather array sizes */ 174 | int * sizes = (int *) malloc(sizeof(int)*p->size); 175 | MPI_Gather(¤t,1,MPI_INT,sizes,1,MPI_INT,0,MPI_COMM_WORLD); 176 | 177 | 178 | /* Determine the displacement in the final array */ 179 | int * disp = (int *) malloc(sizeof(int)*p->size); 180 | if(p->rank == 0) 181 | { 182 | disp[0] = 0; 183 | for(i = 1; i < p->size+1; ++i) 184 | disp[i] = disp[i-1] + sizes[i-1]; 185 | } 186 | 187 | /* For verbose mode */ 188 | if(p->rank == 0 && p->verbose) 189 | for(i = 0; i < p->size; ++i) 190 | { 191 | range_min = disp[i], range_max = disp[i]+sizes[i]; 192 | fprintf(stderr,"Rank [%d] [%d] => [%d] Disp = %d Size = %d\n",i,range_min,range_max, disp[i],sizes[i]); 193 | } 194 | 195 | /* Gather results */ 196 | MPI_Gatherv(large_bucket.array,current,MPI_INT,array,sizes,disp,MPI_INT,0,MPI_COMM_WORLD); 197 | 198 | /* Verbose Mode */ 199 | if(p->rank == 0) 200 | { 201 | end = MPI_Wtime(); 202 | fprintf(stderr,"array size: %d\telapse time: %f\n",p->array_size,end-start); 203 | if(p->print_array) 204 | for(i = 0; i < p->array_size; i++) 205 | fprintf(stdout,"array[%d] = %d\n",i,array[i]); 206 | free(array); 207 | } 208 | return; 209 | } 210 | 211 | void usage() 212 | { 213 | printf("bucket_sort\n\ 214 | MPI Program to sort an array using bucket sort.\n\ 215 | Jharrod LaFon 2011\n\ 216 | Usage: bucket_sort [args]\n\ 217 | -r\t\tPrint bucket ranges\n\ 218 | -s \tSpecify array size\n\ 219 | -m \tSpecify largest number in array\n\ 220 | -p\t\tPrint the array\n\ 221 | -v\t\tBe verbose\n\ 222 | -h\t\tPrint this message\n"); 223 | } 224 | /* Parse user arguments */ 225 | void parse_args(int argc, char ** argv, Params * p) 226 | { 227 | int c = 0; 228 | while((c = getopt(argc,argv,"rs:hm:vp")) != -1) 229 | { 230 | switch(c) 231 | { 232 | case 'r': 233 | p->print_ranges = 1; 234 | break; 235 | case 's': 236 | p->array_size = atoi(optarg); 237 | break; 238 | case 'm': 239 | p->max_num = atoi(optarg); 240 | break; 241 | case 'h': 242 | if(p->rank == 0) usage(); 243 | exit(0); 244 | case 'p': 245 | p->print_array = 1; 246 | break; 247 | case 'v': 248 | p->verbose = 1; 249 | break; 250 | default: 251 | break; 252 | } 253 | } 254 | return; 255 | } 256 | 257 | /* Main */ 258 | int main(int argc, char *argv[]) 259 | { 260 | int rank; 261 | int size; 262 | /* Initialize MPI */ 263 | if(MPI_Init(&argc, &argv) != MPI_SUCCESS) 264 | { 265 | fprintf(stderr, "Unable to initialize MPI!\n"); 266 | return -1; 267 | } 268 | /* Get rank and size */ 269 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); 270 | MPI_Comm_size(MPI_COMM_WORLD, &size); 271 | 272 | /* Populate the parameters with default values */ 273 | Params p; 274 | 275 | /* Don't be verbose by default */ 276 | p.verbose = 0; 277 | p.print_array = 0; 278 | p.print_ranges = 0; 279 | p.rank = rank; 280 | p.size = size; 281 | p.array_size = DEFAULT_ARRAY_SIZE; 282 | p.max_num = MAX_NUM_SIZE; 283 | /* Check for user options */ 284 | parse_args(argc,argv,&p); 285 | if(p.array_size % p.size != 0) 286 | { 287 | if(rank == 0) fprintf(stderr,"Error: Array size must be multiple of number of ranks.\n"); 288 | exit(1); 289 | } 290 | slave(&p); 291 | MPI_Finalize(); 292 | return 0; 293 | 294 | } 295 | -------------------------------------------------------------------------------- /bucket-sort/bucket_sort_pipeline.c: -------------------------------------------------------------------------------- 1 | /* File: bucket_sort.c 2 | Author: Jharrod LaFon 3 | Date: Spring 2011 4 | Purpose: Pipeline implementation of bucket sort 5 | */ 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "memwatch.h" 13 | #define TERM_TAG 5 14 | #define NUM_TAG 10 15 | #define DEFAULT_ARRAY_SIZE 500 16 | #define MAX_NUM_SIZE 30 17 | #define BLOCK_LOW(id,p,n) ((id)*(n)/(p)) 18 | #define BLOCK_HIGH(id,p,n) \ 19 | (BLOCK_LOW((id)+1,p,n)-1) 20 | 21 | /* Struct to hold configuration options */ 22 | typedef struct 23 | { 24 | int rank,size, array_size,slice,max_num,verbose; 25 | } Params; 26 | 27 | /* Struct defining a bucket, that contains index items */ 28 | typedef struct 29 | { 30 | int * array; 31 | int index; 32 | } Bucket; 33 | 34 | /* Inserts x into the bucket, and updates the index */ 35 | void bucket_insert(Bucket * b, int x) 36 | { 37 | b->array[b->index] = x; 38 | b->index = b->index +1; 39 | } 40 | 41 | /* Function to compare two values for sorting, needed for quick sort */ 42 | int compare( const void * n1, const void * n2) 43 | { 44 | return (*(int*)n1 - *(int*)n2); 45 | } 46 | 47 | 48 | /* Function to be executed by the workers */ 49 | void slave(Params * p) 50 | { 51 | srand(2); 52 | /* Timer */ 53 | double start, end; 54 | int i; 55 | int * array; 56 | array = (int *) malloc(sizeof(int) * p->array_size); 57 | MPI_Status status; 58 | int count = 0; 59 | int done = 0; 60 | int temp = 0; 61 | int low = BLOCK_LOW(p->rank-1,p->size,p->max_num+1); 62 | int high = BLOCK_HIGH(p->rank-1,p->size,p->max_num+1); 63 | start = MPI_Wtime(); 64 | // Repeat until done 65 | while(!done) 66 | { 67 | // Master work 68 | if(p->rank == 0) 69 | { 70 | // Increase count until array_size 71 | if(count++ < p->array_size) 72 | { 73 | // Add random number to list, send it up the pipeline to rank 1 74 | temp = rand() % p->max_num; 75 | MPI_Send(&temp, 1, MPI_INT, 1, NUM_TAG, MPI_COMM_WORLD); 76 | } 77 | else 78 | { 79 | // Signal end of the list 80 | MPI_Send(&temp, 1, MPI_INT, 1, TERM_TAG, MPI_COMM_WORLD); 81 | done = 1; 82 | } 83 | } 84 | // Slave work 85 | else 86 | { 87 | // receive a number from the previous stage 88 | MPI_Recv(&temp, 1, MPI_INT, p->rank-1, MPI_ANY_TAG, MPI_COMM_WORLD, &status); 89 | // check for termination 90 | if(status.MPI_TAG == TERM_TAG) 91 | { 92 | // make sure I'm sending to a valid rank and foward termination 93 | done = 1; 94 | if(p->rank != p->size) 95 | { 96 | MPI_Send(&temp, 1, MPI_INT, p->rank+1, TERM_TAG, MPI_COMM_WORLD); 97 | } 98 | } 99 | // got number 100 | else if(status.MPI_TAG == NUM_TAG) 101 | { 102 | // check to see if I keep it 103 | if(temp >= low && temp <= high) 104 | array[count++] = temp; 105 | else 106 | // pass it on 107 | MPI_Send(&temp, 1, MPI_INT, p->rank+1, NUM_TAG,MPI_COMM_WORLD); 108 | } 109 | 110 | } 111 | } 112 | MPI_Barrier(MPI_COMM_WORLD); 113 | int * sizes = (int *) calloc(p->size+1,sizeof(int)); 114 | MPI_Gather(&count, 1, MPI_INT, sizes, 1, MPI_INT, 0 , MPI_COMM_WORLD); 115 | int * disp = (int *) calloc(p->size+1,sizeof(int)); 116 | if(p->rank == 0) 117 | { 118 | sizes[0] = 0; 119 | disp[0] = 0; 120 | for(i = 1; i < p->size+1; ++i) 121 | { 122 | disp[i] = disp[i-1] + sizes[i-1]; 123 | } 124 | 125 | } 126 | // sort the array, except for the master 127 | if(p->rank != 0) 128 | qsort(array,count,sizeof(int),compare); 129 | if(p->rank == 0) count = 0; 130 | // gather results 131 | MPI_Gatherv(array, count, MPI_INT, &array[0], sizes, disp, MPI_INT,0,MPI_COMM_WORLD); 132 | // stop the clock, print results 133 | end = MPI_Wtime(); 134 | if(p->rank ==0) fprintf(stderr,"[%d] Elapsed time: %f\n",p->rank,end-start); 135 | return; 136 | } 137 | 138 | void usage() 139 | { 140 | printf("bucket_sort\n\ 141 | MPI Program to sort an array using bucket sort.\n\ 142 | Jharrod LaFon 2011\n\ 143 | Usage: bucket_sort [args]\n\ 144 | -r\t\tPrint bucket ranges\n\ 145 | -s \tSpecify array size\n\ 146 | -m \tSpecify largest number in array\n\ 147 | -p\t\tPrint the array\n\ 148 | -v\t\tBe verbose\n\ 149 | -h\t\tPrint this message\n"); 150 | } 151 | /* Parse user arguments */ 152 | void parse_args(int argc, char ** argv, Params * p) 153 | { 154 | int c = 0; 155 | while((c = getopt(argc,argv,"s:hm:v")) != -1) 156 | { 157 | switch(c) 158 | { 159 | case 's': 160 | p->array_size = atoi(optarg); 161 | break; 162 | case 'm': 163 | p->max_num = atoi(optarg); 164 | break; 165 | case 'h': 166 | if(p->rank == 0) usage(); 167 | exit(0); 168 | case 'v': 169 | p->verbose = 1; 170 | break; 171 | default: 172 | break; 173 | } 174 | } 175 | return; 176 | } 177 | 178 | /* Main */ 179 | int main(int argc, char *argv[]) 180 | { 181 | int rank; 182 | int size; 183 | /* Initialize MPI */ 184 | if(MPI_Init(&argc, &argv) != MPI_SUCCESS) 185 | { 186 | fprintf(stderr, "Unable to initialize MPI!\n"); 187 | return -1; 188 | } 189 | /* Get rank and size */ 190 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); 191 | MPI_Comm_size(MPI_COMM_WORLD, &size); 192 | 193 | 194 | /* Populate the parameters with default values */ 195 | Params p; 196 | 197 | /* Don't be verbose by default */ 198 | p.verbose = 0; 199 | p.rank = rank; 200 | 201 | // Used for cleaner code later on 202 | p.size = size - 1; 203 | 204 | p.array_size = DEFAULT_ARRAY_SIZE; 205 | p.max_num = MAX_NUM_SIZE; 206 | /* Check for user options */ 207 | parse_args(argc,argv,&p); 208 | slave(&p); 209 | MPI_Finalize(); 210 | return 0; 211 | 212 | } 213 | -------------------------------------------------------------------------------- /goldberg-conjecture/Makefile: -------------------------------------------------------------------------------- 1 | LIBS += -lm -lrt -fopenmp 2 | CFLAGS += -Wall 3 | 4 | all: goldberg 5 | 6 | goldberg: goldberg.c 7 | $(CC) $(INCLUDE) $(LIBS) $(CFLAGS) $@.c -o $@ 8 | 9 | clean: 10 | - /bin/rm -f goldberg.c 11 | - /bin/rm -f *.o 12 | - /bin/rm -f *.x 13 | 14 | -------------------------------------------------------------------------------- /goldberg-conjecture/goldberg.c: -------------------------------------------------------------------------------- 1 | /* File: golberg.c 2 | Authors: Jharrod LaFon, Michael Harris 3 | Date: Spring 2011 4 | Purpose: Test Goldberg's Conjecture 5 | */ 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #define MAX 500 14 | #define MIN 2 15 | 16 | // returns 1 if number p is prime, 0 otherwise 17 | int prime(int p) 18 | { 19 | int result = 1; 20 | int i; 21 | for(i = 2; i < sqrt(p); i++) 22 | if(p % i == 0) 23 | { 24 | result = 0; 25 | break; 26 | } 27 | return result; 28 | } 29 | 30 | // returns the number of combinations of primes that equal p 31 | int gold(int p) 32 | { 33 | int result = 0; 34 | int i,j; 35 | for(i=0;i\t\tNumber of threads\n\ 46 | -s \t\tSchedule.\n\ 47 | \t\t\tStatic\t1\n\ 48 | \t\t\tDynamic\t2\n\ 49 | \t\t\tGuided\t3\n\ 50 | \t\t\tAuto\t4\n\ 51 | -m \t\tSchedule modifier\n\ 52 | \t\t\tFor Dynamic,guided & static this is the chunk size\n\ 53 | -h\t\t\tPrint this message\n"); 54 | } 55 | int main(int argc, char*argv[]) 56 | { 57 | int max = MAX; 58 | int min = MIN; 59 | int size = (max-min)/2; 60 | int * array = (int*) malloc(sizeof(int)*size); 61 | int i; 62 | struct timespec start, end,elapsed; 63 | int c = 0; 64 | int num_threads = 1; 65 | int modifier = 0; 66 | omp_sched_t schedule = 1; 67 | while((c = getopt(argc,argv,"n:s:m:h")) != -1) 68 | { 69 | switch(c) 70 | { 71 | case 'n': 72 | num_threads = atoi(optarg); 73 | break; 74 | case 's': 75 | schedule = atoi(optarg); 76 | break; 77 | case 'm': 78 | modifier = atoi(optarg); 79 | break; 80 | case 'h': 81 | usage(); 82 | exit(0); 83 | default: 84 | break; 85 | } 86 | } 87 | omp_set_num_threads(num_threads); 88 | omp_set_schedule(schedule,modifier); 89 | clock_gettime(CLOCK_REALTIME, &start); 90 | for(i = 1; i < size; i++) 91 | array[i] = 0; 92 | #pragma omp parallel for 93 | for(i = 1; i < size; i++) 94 | array[i] = gold(2*i); 95 | #pragma omp parallel for 96 | for(i = 1; i < size; i++) 97 | if(array[i] == 0) 98 | fprintf(stdout,"Violated at %d\n",2*i); 99 | clock_gettime(CLOCK_REALTIME, &end); 100 | elapsed.tv_sec = end.tv_sec - start.tv_sec; 101 | elapsed.tv_nsec = end.tv_nsec - start.tv_nsec; 102 | if(elapsed.tv_nsec < 0) 103 | { 104 | elapsed.tv_sec -= 1; 105 | elapsed.tv_nsec += 1000000000; 106 | } 107 | printf("%ld.%ld\n",elapsed.tv_sec,elapsed.tv_nsec); 108 | return 0; 109 | } 110 | -------------------------------------------------------------------------------- /image-manip/image_manip.c: -------------------------------------------------------------------------------- 1 | /* File: image_manip.c 2 | Authors: Jharrod LaFon, Gholamali Rahnavard 3 | Date: Spring 2011 4 | Purpose: Low level parallel image manipulation. 5 | */ 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #define BM 0x4D42 // Value of a bitmap type 14 | #define MAX_FILENAME 256 15 | #define PI 3.14159265 16 | #define BLOCK_LOW(id,p,n) ((id)*(n)/(p)) 17 | #define BLOCK_HIGH(id,p,n) \ 18 | (BLOCK_LOW((id)+1,p,n)-1) 19 | #define BLOCK_SIZE(id,p,n) \ 20 | (BLOCK_LOW((id)+1)-BLOCK_LOW(id)) 21 | #define BLOCK_OWNER(index,p,n) \ 22 | (((p)*((index)+1)-1)/(n)) 23 | 24 | // Struct to hold a 2d vector 25 | #pragma pack(push, 1) 26 | typedef struct Vector 27 | { 28 | int x,y; 29 | } Vector; 30 | #pragma pack(pop) 31 | typedef enum { NS, SHIFT, SCALE, ROTATE } operation; 32 | typedef struct Options 33 | { 34 | operation op; 35 | char * inputfile; 36 | char * filename; 37 | Vector v; 38 | double param; 39 | int flag; 40 | void (*func)(Vector *v, Vector *r, int p, int row, double sf); 41 | } Options; 42 | 43 | // BITMAP header 44 | #pragma pack(push, 1) 45 | typedef struct 46 | { 47 | uint16_t type; 48 | uint32_t size; 49 | uint16_t reserved1, reserved2; 50 | uint32_t offset; 51 | } HEADER; 52 | #pragma pack(pop) 53 | 54 | // BITMAP information header 55 | #pragma pack(push, 1) 56 | typedef struct 57 | { 58 | uint32_t size; 59 | int32_t width, height; 60 | uint16_t planes; 61 | uint16_t bits; 62 | uint32_t compression; 63 | uint32_t isize; 64 | int32_t xres,yres; 65 | uint32_t colors; 66 | uint32_t impcolors; 67 | } IHEADER; 68 | #pragma pack(pop) 69 | 70 | // Pixel 71 | #pragma pack(push, 1) 72 | typedef struct Pixel 73 | { 74 | uint8_t b,g,r; 75 | } Pixel; 76 | #pragma pack(pop) 77 | 78 | // Struct to hold info on a bitmap 79 | #pragma pack(push, 1) 80 | typedef struct 81 | 82 | HEADER header; 83 | IHEADER iheader; 84 | Pixel ** array; 85 | } BMP; 86 | #pragma pack(pop) 87 | 88 | // Printed if a filename is not supplied 89 | void usage() 90 | { 91 | //while((c = getopt(argc, argv, "f:o:x:y:r:s:")) != -1) 92 | printf("Usage: image_manip: -f [OPTS]\n\ 93 | The program can be run without the following options for a menu.\n\ 94 | Otherwise, an output file name is required.\n\ 95 | Operations are mutually exclusive.\n\ 96 | -o \tName of output file.\n\ 97 | -x \t\tAmount to shift in x direction. Requires -y\n\ 98 | -y \t\tAmount to shift in y direction. Requires -x\n\ 99 | -r \t\tAmount to rotate image.\n\ 100 | -s \t\tAmount to scale image.\n"); 101 | exit(1); 102 | } 103 | void shift(Vector * v, Vector * r, int p, int row, double sf) 104 | { 105 | (*r).x = p + (*v).x; 106 | (*r).y = row + (*v).y; 107 | } 108 | void scale(Vector * v, Vector * r, int p, int row, double sf) 109 | { 110 | (*r).x = (int)p*sf; 111 | (*r).y = (int)row*sf; 112 | } 113 | void rotate(Vector * v, Vector *r, int p, int row, double sf) 114 | { 115 | (*r).x = (int)p*cos(sf*PI/180)+row*sin(sf*PI/180); 116 | (*r).y = (int)-1*p*sin(sf*PI/180)+row*cos(sf*PI/180); 117 | } 118 | 119 | 120 | // Performs an image shift 121 | void do_op(BMP * img, Options * opt) 122 | { 123 | int rank, size; 124 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); 125 | MPI_Comm_size(MPI_COMM_WORLD, &size); 126 | // Number of bits in a line 127 | int linebits = (*img).iheader.width * (*img).iheader.bits; 128 | // 4 byte alignment 129 | int linebytes = ((linebits + 31)/32)*4; 130 | Pixel * current; 131 | Vector newvec; 132 | // Accounting 133 | int row = 0; 134 | int p = 0; 135 | int count = sizeof(Pixel)*linebytes; 136 | MPI_Status status; 137 | // Master 138 | if(rank == 0) 139 | { 140 | // Open the new file 141 | FILE * nf; 142 | nf = fopen((*opt).filename,"w"); 143 | // Make sure we are at the beginning 144 | fseek(nf,0,SEEK_SET); 145 | 146 | // Write the headers 147 | fwrite(&(*img).header,1,sizeof((*img).header),nf); 148 | fwrite(&(*img).iheader,1,sizeof((*img).iheader),nf); 149 | 150 | // Allocate memory for a new pixel array 151 | Pixel ** newimg = malloc(sizeof(Pixel*) * (*img).iheader.height); 152 | 153 | // For every row 154 | for(row = 0; row < (*img).iheader.height; row++) 155 | { 156 | current = (Pixel *) malloc(sizeof(Pixel)*linebytes); 157 | memset(current,0,sizeof(Pixel)*linebytes); 158 | MPI_Recv(current, count,MPI_BYTE, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status); 159 | newimg[status.MPI_TAG] = current; 160 | } 161 | // Write the new image 162 | for(row = (*img).iheader.height-1; row >= 0; row--) 163 | fwrite(&newimg[row][0],1,linebytes,nf); 164 | fclose(nf); 165 | free(newimg); 166 | 167 | } 168 | else 169 | { 170 | current = (Pixel *) malloc(sizeof(Pixel)*linebytes); 171 | // For every row 172 | int r = BLOCK_LOW(rank-1,size-1,(*img).iheader.height); 173 | Pixel blank; 174 | blank.r = blank.g = blank.b = 0; 175 | 176 | for(row = r; row <= BLOCK_HIGH(rank-1,size-1,(*img).iheader.height); row++) 177 | { 178 | // fprintf(stderr,"Rank,row [%d][%d]\n",rank,row); 179 | // Set the memory to 0 by default (black), this also pads zeroes 180 | memset(current,0,sizeof(current)); 181 | 182 | // For every pixel in the row (3 bytes) 183 | for(p = 0; p < linebytes/3; p++) 184 | { 185 | // Calc x,y 186 | (*opt).func(&(*opt).v, &newvec, p, row, (*opt).param); 187 | // Make sure they are on the canvas 188 | if(newvec.x >= 0 && newvec.x < linebytes/3 && newvec.y < (*img).iheader.height && newvec.y >= 0) 189 | current[p] = (*img).array[newvec.y][newvec.x]; 190 | else 191 | current[p] = blank; 192 | } 193 | MPI_Send(current, count, MPI_BYTE, 0, row, MPI_COMM_WORLD); 194 | } 195 | } 196 | // fprintf(stderr, "Rank %d: %d->%d\n",rank,BLOCK_LOW(rank-1,size-1,(*img).iheader.height),BLOCK_HIGH(rank-1,size-1,(*img).iheader.height)); 197 | free(current); 198 | } 199 | 200 | 201 | 202 | // Program menu 203 | int do_menu(BMP * img, Options * opts) 204 | { 205 | int rank,size; 206 | int choice; 207 | char * name = (char *) malloc(sizeof(char) * MAX_FILENAME); 208 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); 209 | MPI_Comm_size(MPI_COMM_WORLD, &size); 210 | //fprintf(stderr,"[%s][%d] %d\n",__FILE__,__LINE__,rank); 211 | if(rank == 0) 212 | { 213 | printf("\ 214 | Options\n\ 215 | =======\n\ 216 | 1. Shift\n\ 217 | 2. Scale\n\ 218 | 3. Rotate\n\ 219 | 4. Exit\n\ 220 | Enter a selection: "); 221 | fflush(stdout); 222 | scanf("%d",&choice); 223 | if(choice == 1 || choice == 2 || choice == 3) 224 | { 225 | printf("Enter a filename for the new image: "); 226 | fflush(stdout); 227 | scanf("%s",name); 228 | (*opts).filename = name; 229 | } 230 | } 231 | // \TODO: Merge this 232 | if(rank == 0) 233 | { 234 | switch(choice) 235 | { 236 | case 1: 237 | printf("Enter integer delta x: "); 238 | fflush(stdout); 239 | scanf("%d",&(*opts).v.x); 240 | printf("Enter integer delta y: "); 241 | fflush(stdout); 242 | scanf("%d",&(*opts).v.y); 243 | (*opts).func = shift; 244 | break; 245 | case 2: 246 | printf("Enter a decimal scale factor: "); 247 | fflush(stdout); 248 | scanf("%lf",&(*opts).param); 249 | (*opts).func = scale; 250 | break; 251 | case 3: 252 | printf("Enter decimal degrees to rotate: "); 253 | fflush(stdout); 254 | scanf("%lf",&(*opts).param); 255 | (*opts).func = rotate; 256 | break; 257 | case 4: 258 | return 0; 259 | break; 260 | default: break; 261 | } 262 | } 263 | MPI_Bcast(opts,sizeof(*opts),MPI_BYTE,0,MPI_COMM_WORLD); 264 | do_op(img, opts); 265 | 266 | return 0; 267 | } 268 | 269 | // Read bitmap header 270 | int get_bmp_header(FILE * fp, BMP * img) 271 | { 272 | if(sizeof((*img).header) != fread(&(*img).header,1,sizeof((*img).header),fp)) 273 | { 274 | perror("Unable to read file"); 275 | exit(1); 276 | } 277 | if(sizeof((*img).iheader) != fread(&(*img).iheader,1,sizeof((*img).iheader),fp)) 278 | { 279 | perror("Unable to read file"); 280 | exit(1); 281 | } 282 | if((*img).header.type != BM) 283 | { 284 | printf("Error: Not a valid bitmap file.\n"); 285 | exit(1); 286 | } 287 | return 0; 288 | } 289 | 290 | // Print attributes 291 | int print_bmp_attr(BMP * bmp) 292 | { 293 | printf("File: \n\t\ 294 | Type: %X\n\t\ 295 | Size: %d\n\t\ 296 | Offset: %d\n\t\ 297 | Width: %d\n\t\ 298 | Height: %d\n\t\ 299 | Image Size: %u\n\t\ 300 | Bits/Pixel: %u\n\t\ 301 | Compression: %u\n\t\ 302 | Number of colors: %u\n\t\ 303 | Important colors: %u\n", (*bmp).header.type, (*bmp).header.size, (*bmp).header.offset,(*bmp).iheader.width,(*bmp).iheader.height,(*bmp).iheader.isize, (*bmp).iheader.bits, (*bmp).iheader.compression,(*bmp).iheader.colors,(*bmp).iheader.impcolors); 304 | return 0; 305 | } 306 | 307 | void parse_args(int argc, char **argv, Options * opts) 308 | { 309 | // Parse options 310 | int c = 0; 311 | while((c = getopt(argc, argv, "f:o:x:y:r:s:")) != -1) 312 | { 313 | switch(c) 314 | { 315 | case 'f': 316 | (*opts).inputfile = optarg; 317 | break; 318 | case 'o': 319 | (*opts).filename = optarg; 320 | break; 321 | case 'x': 322 | (*opts).flag++; 323 | (*opts).op = SHIFT; 324 | (*opts).func = shift; 325 | (*opts).v.x = atoi(optarg); 326 | break; 327 | case 'y': 328 | (*opts).flag++; 329 | (*opts).v.y = atoi(optarg); 330 | break; 331 | case 'r': 332 | (*opts).op = ROTATE; 333 | (*opts).func = rotate; 334 | (*opts).param = atof(optarg); 335 | break; 336 | case 's': 337 | (*opts).op = SCALE; 338 | (*opts).func = scale; 339 | (*opts).param = atof(optarg); 340 | default: 341 | break; 342 | } 343 | } 344 | 345 | } 346 | 347 | // Main 348 | int main(int argc, char **argv) 349 | { 350 | if(MPI_Init(&argc,&argv) != MPI_SUCCESS) 351 | { 352 | perror("Unable to initialize MPI\n"); 353 | exit(1); 354 | } 355 | 356 | FILE * fp = 0; 357 | BMP bmp; 358 | Options opts; 359 | opts.op = NS; 360 | opts.filename = 0; 361 | opts.flag = 0; 362 | parse_args(argc, argv, &opts); 363 | if((fp = fopen(opts.inputfile,"rw")) == NULL) 364 | { 365 | usage(); 366 | perror("Unable to open file"); 367 | exit(1); 368 | } 369 | get_bmp_header(fp, &bmp); 370 | // print_bmp_attr(&bmp); 371 | int linebits = bmp.iheader.width * bmp.iheader.bits; 372 | int linebytes = ((linebits + 31)/32)*4; 373 | Pixel ** img = malloc(sizeof(Pixel*) * bmp.iheader.height); 374 | fseek(fp, bmp.header.offset, SEEK_SET); 375 | int row = 0; 376 | int byte = 0; 377 | int column = 0; 378 | //int rank, size; 379 | Pixel * current; 380 | for(row = bmp.iheader.height-1; row >= 0; row--) 381 | { 382 | current = (Pixel *) malloc(linebytes); 383 | column = 0; 384 | for(byte = 0; byte < linebytes; byte+=3) 385 | { 386 | fread(¤t[column++],1,sizeof(Pixel),fp); 387 | } 388 | img[row] = current; 389 | fseek(fp, bmp.header.offset + (bmp.iheader.height-1-row) * linebytes, SEEK_SET); 390 | } 391 | fclose(fp); 392 | bmp.array = img; 393 | if(opts.op == NS) 394 | do_menu(&bmp,&opts); 395 | else if(opts.filename == 0) 396 | usage(); 397 | else 398 | { 399 | switch(opts.op) 400 | { 401 | case SCALE: 402 | opts.func = scale; 403 | break; 404 | case SHIFT: 405 | if(opts.flag == 2) 406 | opts.func = shift; 407 | else 408 | usage(); 409 | break; 410 | case ROTATE: 411 | opts.func = rotate; 412 | break; 413 | case NS: 414 | default: 415 | usage(); 416 | break; 417 | 418 | } 419 | do_op(&bmp, &opts); 420 | 421 | } 422 | free(img); 423 | MPI_Finalize(); 424 | return 0; 425 | } 426 | -------------------------------------------------------------------------------- /image-manip/image_manip_serial.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #define BM 0x4D42 // Value of a bitmap type 8 | #define MAX_FILENAME 256 9 | #define PI 3.14159265 10 | // Struct to hold a 2d vector 11 | #pragma pack(push, 1) 12 | typedef struct Vector 13 | { 14 | int x,y; 15 | } Vector; 16 | #pragma pack(pop) 17 | 18 | typedef enum { NS, SHIFT, SCALE, ROTATE } operation; 19 | typedef struct Options 20 | { 21 | operation op; 22 | char * filename; 23 | Vector v; 24 | double theta; 25 | double scalefactor; 26 | } Options; 27 | // BITMAP header 28 | #pragma pack(push, 1) 29 | typedef struct 30 | { 31 | uint16_t type; 32 | uint32_t size; 33 | uint16_t reserved1, reserved2; 34 | uint32_t offset; 35 | } HEADER; 36 | #pragma pack(pop) 37 | 38 | // BITMAP information header 39 | #pragma pack(push, 1) 40 | typedef struct 41 | { 42 | uint32_t size; 43 | int32_t width, height; 44 | uint16_t planes; 45 | uint16_t bits; 46 | uint32_t compression; 47 | uint32_t isize; 48 | int32_t xres,yres; 49 | uint32_t colors; 50 | uint32_t impcolors; 51 | } IHEADER; 52 | #pragma pack(pop) 53 | 54 | // Pixel 55 | #pragma pack(push, 1) 56 | typedef struct Pixel 57 | { 58 | uint8_t b,g,r; 59 | } Pixel; 60 | #pragma pack(pop) 61 | 62 | // Struct to hold info on a bitmap 63 | #pragma pack(push, 1) 64 | typedef struct 65 | { 66 | HEADER header; 67 | IHEADER iheader; 68 | Pixel ** array; 69 | } BMP; 70 | #pragma pack(pop) 71 | 72 | // Printed if a filename is not supplied 73 | void usage() 74 | { 75 | //while((c = getopt(argc, argv, "f:o:x:y:r:s:")) != -1) 76 | printf("Usage: image_manip: -f [OPTS]\n\ 77 | The program can be run without the following options for a menu.\n\ 78 | Otherwise, an output file name is required.\n\ 79 | Operations are mutually exclusive.\n\ 80 | -o \tName of output file.\n\ 81 | -x \t\tAmount to shift in x direction. Requires -y\n\ 82 | -y \t\tAmount to shift in y direction. Requires -x\n\ 83 | -r \t\tAmount to rotate image.\n\ 84 | -s \t\tAmount to scale image.\n"); 85 | exit(1); 86 | } 87 | 88 | // Performs an image shift 89 | void shift(BMP * img, Vector * v, char * file) 90 | { 91 | // Number of bits in a line 92 | int linebits = (*img).iheader.width * (*img).iheader.bits; 93 | // 4 byte alignment 94 | int linebytes = ((linebits + 31)/32)*4; 95 | 96 | // Allocate memory for a new pixel array 97 | Pixel ** newimg = malloc(sizeof(Pixel*) * (*img).iheader.height); 98 | 99 | // Accounting 100 | int row = 0; 101 | int p = 0; 102 | int xp, yp; 103 | Pixel * current; 104 | 105 | // Open the new file 106 | FILE * nf; 107 | nf = fopen(file,"w"); 108 | 109 | // Make sure we are at the beginning 110 | fseek(nf,0,SEEK_SET); 111 | 112 | // Write the headers 113 | fwrite(&(*img).header,1,sizeof((*img).header),nf); 114 | fwrite(&(*img).iheader,1,sizeof((*img).iheader),nf); 115 | 116 | // For every row 117 | for(row = 0; row < (*img).iheader.height; row++) 118 | { 119 | // Get memory for this row 120 | current = (Pixel *) malloc(sizeof(Pixel)*linebytes); 121 | 122 | // Set the memory to 0 by default (black), this also pads zeroes 123 | memset(current,0,sizeof(current)); 124 | 125 | // For every pixel in the row (3 bytes) 126 | for(p = 0; p < linebytes/3; p++) 127 | { 128 | // Calculate the new x,y 129 | xp = p + (*v).x; 130 | yp = row + (*v).y; 131 | // Make sure they are on the canvas 132 | if(xp >= 0 && xp < linebytes/3 && yp < (*img).iheader.height && yp >= 0) 133 | { 134 | current[p] = (*img).array[yp][xp]; 135 | } 136 | } 137 | // Store this row 138 | newimg[row] = current; 139 | } 140 | 141 | // Write the new image 142 | for(row = (*img).iheader.height-1; row >= 0; row--) 143 | fwrite(&newimg[row][0],1,linebytes,nf); 144 | fclose(nf); 145 | free(newimg); 146 | } 147 | 148 | // Scales an image up or down 149 | void scale(BMP * img, double sf, char * file) 150 | { 151 | // Number of bits in a line 152 | int linebits = (*img).iheader.width * (*img).iheader.bits; 153 | // 4 byte alignment 154 | int linebytes = ((linebits + 31)/32)*4; 155 | 156 | // Allocate memory for a new pixel array 157 | Pixel ** newimg = malloc(sizeof(Pixel*) * (*img).iheader.height); 158 | 159 | // Accounting 160 | int row = 0; 161 | int p = 0; 162 | int xp, yp; 163 | Pixel * current; 164 | 165 | // Open the new file 166 | FILE * nf; 167 | nf = fopen(file,"w"); 168 | 169 | // Make sure we are at the beginning 170 | fseek(nf,0,SEEK_SET); 171 | 172 | // Write the headers 173 | fwrite(&(*img).header,1,sizeof((*img).header),nf); 174 | fwrite(&(*img).iheader,1,sizeof((*img).iheader),nf); 175 | 176 | // For every row 177 | for(row = 0; row < (*img).iheader.height; row++) 178 | { 179 | // Get memory for this row 180 | current = (Pixel *) malloc(sizeof(Pixel)*linebytes); 181 | 182 | // Set the memory to 0 by default (black), this also pads zeroes 183 | memset(current,0,sizeof(current)); 184 | 185 | // For every pixel in the row (3 bytes) 186 | for(p = 0; p < linebytes/3; p++) 187 | { 188 | // Calculate the new x,y 189 | xp = (int)p*sf; 190 | yp = (int)row*sf; 191 | // Make sure they are on the canvas 192 | if(xp >= 0 && xp < linebytes/3 && yp < (*img).iheader.height && yp >= 0) 193 | { 194 | current[p] = (*img).array[yp][xp]; 195 | } 196 | } 197 | // Store this row 198 | newimg[row] = current; 199 | } 200 | 201 | // Write the new image 202 | for(row = (*img).iheader.height-1; row >= 0; row--) 203 | fwrite(&newimg[row][0],1,linebytes,nf); 204 | fclose(nf); 205 | free(newimg); 206 | 207 | } 208 | 209 | void rotate(BMP * img, double theta, char * file) 210 | { 211 | // Number of bits in a line 212 | int linebits = (*img).iheader.width * (*img).iheader.bits; 213 | // 4 byte alignment 214 | int linebytes = ((linebits + 31)/32)*4; 215 | 216 | // Allocate memory for a new pixel array 217 | Pixel ** newimg = malloc(sizeof(Pixel*) * (*img).iheader.height); 218 | 219 | // Accounting 220 | int row = 0; 221 | int p = 0; 222 | int xp, yp; 223 | Pixel * current; 224 | 225 | // Open the new file 226 | FILE * nf; 227 | nf = fopen(file,"w"); 228 | 229 | // Make sure we are at the beginning 230 | fseek(nf,0,SEEK_SET); 231 | 232 | // Write the headers 233 | fwrite(&(*img).header,1,sizeof((*img).header),nf); 234 | fwrite(&(*img).iheader,1,sizeof((*img).iheader),nf); 235 | 236 | // For every row 237 | for(row = 0; row < (*img).iheader.height; row++) 238 | { 239 | // Get memory for this row 240 | current = (Pixel *) malloc(sizeof(Pixel)*linebytes); 241 | 242 | // Set the memory to 0 by default (black), this also pads zeroes 243 | memset(current,0,sizeof(current)); 244 | 245 | // For every pixel in the row (3 bytes) 246 | for(p = 0; p < linebytes/3; p++) 247 | { 248 | // Calculate the new x,y 249 | xp = (int)p*cos(theta*PI/180)+row*sin(theta*PI/180); 250 | yp = (int)-1*p*sin(theta*PI/180)+row*cos(theta*PI/180); 251 | // Make sure they are on the canvas 252 | if(xp >= 0 && xp < linebytes/3 && yp < (*img).iheader.height && yp >= 0) 253 | { 254 | // new image array[row][p] = old image array [yp][xp] 255 | current[p] = (*img).array[yp][xp]; 256 | } 257 | } 258 | // Store this row 259 | newimg[row] = current; 260 | } 261 | 262 | // Write the new image 263 | for(row = (*img).iheader.height-1; row >= 0; row--) 264 | fwrite(&newimg[row][0],1,linebytes,nf); 265 | fclose(nf); 266 | free(newimg); 267 | 268 | 269 | } 270 | 271 | // Program menu 272 | int do_menu(BMP * img) 273 | { 274 | fflush(stdout); 275 | printf("\ 276 | Options\n\ 277 | =======\n\ 278 | 1. Shift\n\ 279 | 2. Scale\n\ 280 | 3. Rotate\n\ 281 | 4. Exit\n\ 282 | Enter a selection: "); 283 | int choice; 284 | double sf; 285 | double theta; 286 | char * name = (char *) malloc(sizeof(char) * MAX_FILENAME); 287 | struct Vector v; 288 | scanf("%d",&choice); 289 | if(choice == 1 || choice == 2 || choice == 3) 290 | { 291 | printf("Enter a filename for the new image: "); 292 | scanf("%s",name); 293 | } 294 | switch(choice) 295 | { 296 | case 1: 297 | printf("Enter integer delta x: "); 298 | scanf("%d",&v.x); 299 | printf("Enter integer delta y: "); 300 | scanf("%d",&v.y); 301 | shift(img,&v,name); 302 | break; 303 | case 2: 304 | printf("Enter a decimal scale factor: "); 305 | scanf("%lf",&sf); 306 | scale(img,sf,name); 307 | break; 308 | case 3: 309 | printf("Enter decimal degrees to rotate: "); 310 | scanf("%lf",&theta); 311 | rotate(img,theta,name); 312 | break; 313 | case 4: 314 | return 0; 315 | break; 316 | default: break; 317 | } 318 | return 0; 319 | } 320 | 321 | // Read bitmap header 322 | int get_bmp_header(FILE * fp, BMP * img) 323 | { 324 | if(sizeof((*img).header) != fread(&(*img).header,1,sizeof((*img).header),fp)) 325 | { 326 | perror("Unable to read file"); 327 | exit(1); 328 | } 329 | if(sizeof((*img).iheader) != fread(&(*img).iheader,1,sizeof((*img).iheader),fp)) 330 | { 331 | perror("Unable to read file"); 332 | exit(1); 333 | } 334 | if((*img).header.type != BM) 335 | { 336 | printf("Error: Not a valid bitmap file.\n"); 337 | exit(1); 338 | } 339 | return 0; 340 | } 341 | 342 | // Print attributes 343 | int print_bmp_attr(BMP * bmp) 344 | { 345 | int linebits = (*bmp).iheader.width * (*bmp).iheader.bits; 346 | int linebytes = ((linebits + 31)/32)*4; 347 | printf("File: \n\t\ 348 | Linebytes: %d\n\t\ 349 | Type: %X\n\t\ 350 | Size: %d\n\t\ 351 | Offset: %d\n\t\ 352 | Size: %d\n\t\ 353 | Res1: %d\n\t\ 354 | Res2: %d\n\t\ 355 | Width: %d\n\t\ 356 | Height: %d\n\t\ 357 | Image Size: %u\n\t\ 358 | Xres: %u\n\t\ 359 | Yres: %u\n\t\ 360 | Planes: %u\n\t\ 361 | Bits/Pixel: %u\n\t\ 362 | Compression: %u\n\t\ 363 | Number of colors: %u\n\t\ 364 | Important colors: %u\n", linebytes,(*bmp).header.type, (*bmp).header.size, (*bmp).header.offset,(*bmp).iheader.size,(*bmp).header.reserved1,(*bmp).header.reserved2,(*bmp).iheader.width,(*bmp).iheader.height,(*bmp).iheader.isize, 365 | (*bmp).iheader.xres, (*bmp).iheader.yres,(*bmp).iheader.planes,(*bmp).iheader.bits, (*bmp).iheader.compression,(*bmp).iheader.colors,(*bmp).iheader.impcolors); 366 | return 0; 367 | } 368 | 369 | 370 | // Main 371 | int main(int argc, char **argv) 372 | { 373 | int c = 0; 374 | char *file = 0; 375 | FILE * fp = 0; 376 | int flag = 0; 377 | BMP bmp; 378 | Options opts; 379 | opts.op = NS; 380 | opts.filename = 0; 381 | // Parse options 382 | while((c = getopt(argc, argv, "f:o:x:y:r:s:")) != -1) 383 | { 384 | switch(c) 385 | { 386 | case 'f': 387 | file = optarg; 388 | break; 389 | case 'o': 390 | opts.filename = optarg; 391 | break; 392 | case 'x': 393 | flag++; 394 | opts.op = SHIFT; 395 | opts.v.x = atoi(optarg); 396 | break; 397 | case 'y': 398 | flag++; 399 | opts.op = SHIFT; 400 | opts.v.y = atoi(optarg); 401 | break; 402 | case 'r': 403 | opts.op = ROTATE; 404 | opts.theta = atof(optarg); 405 | break; 406 | case 's': 407 | opts.op = SCALE; 408 | opts.scalefactor = atof(optarg); 409 | default: 410 | break; 411 | } 412 | } 413 | if((fp = fopen(file,"rw")) == NULL) 414 | { 415 | perror("Unable to open file"); 416 | exit(1); 417 | } 418 | 419 | get_bmp_header(fp, &bmp); 420 | print_bmp_attr(&bmp); 421 | int linebits = bmp.iheader.width * bmp.iheader.bits; 422 | int linebytes = ((linebits + 31)/32)*4; 423 | Pixel ** img = malloc(sizeof(Pixel*) * bmp.iheader.height); 424 | fseek(fp, bmp.header.offset, SEEK_SET); 425 | int row = 0; 426 | int byte = 0; 427 | int column = 0; 428 | Pixel * current; 429 | for(row = bmp.iheader.height-1; row >= 0; row--) 430 | { 431 | current = (Pixel *) malloc(linebytes); 432 | column = 0; 433 | for(byte = 0; byte < linebytes; byte+=3) 434 | { 435 | fread(¤t[column++],1,sizeof(Pixel),fp); 436 | } 437 | img[row] = current; 438 | fseek(fp, bmp.header.offset + (bmp.iheader.height-1-row) * linebytes, SEEK_SET); 439 | } 440 | fclose(fp); 441 | bmp.array = img; 442 | if(opts.op == NS) 443 | do_menu(&bmp); 444 | else if(opts.filename == 0) 445 | usage(); 446 | else 447 | { 448 | switch(opts.op) 449 | { 450 | case SCALE: 451 | scale(&bmp,opts.scalefactor,opts.filename); 452 | break; 453 | case SHIFT: 454 | if(flag == 2) 455 | shift(&bmp,&opts.v,opts.filename); 456 | else 457 | usage(); 458 | break; 459 | case ROTATE: 460 | rotate(&bmp,opts.theta,opts.filename); 461 | break; 462 | case NS: 463 | default: 464 | usage(); 465 | break; 466 | 467 | } 468 | 469 | } 470 | free(img); 471 | return 0; 472 | } 473 | -------------------------------------------------------------------------------- /integration/integration.c: -------------------------------------------------------------------------------- 1 | /* File: integration.c 2 | Author: Jharrod LaFon 3 | Date: Spring 2011 4 | Purpose: Compute the approximation of the integral of f(x) 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | /* Integration Interval */ 15 | #define INTERVAL_MIN 0.0 16 | #define INTERVAL_MAX 1.0 17 | /* Starting number of intervals */ 18 | #define NUM_INTERVALS 1 19 | /* Default Error Threshold */ 20 | #define ERROR_THRESHOLD 0.00001 21 | 22 | /* Struct to hold configuration options */ 23 | typedef struct 24 | { 25 | int intervals,rank,size; 26 | double delta,region; 27 | double error; 28 | double min,max; 29 | double (*func)(double start, double end, double delta); 30 | } Params; 31 | 32 | /* Function f(x) to be integrated */ 33 | double f(double x) 34 | { 35 | return sqrt(1-x*x); 36 | } 37 | 38 | /* Approximation of f(x) using the rectangle rule */ 39 | double rectangle_rule(double start, double end, double delta) 40 | { 41 | double area = 0.0; 42 | double x; 43 | for(x = start; x <= end; x+= delta) 44 | area += f(x)*delta; 45 | return area; 46 | } 47 | 48 | /* Approximation of f(x) using the trapezoid rule */ 49 | double trapezoid_rule(double start, double end, double delta) 50 | { 51 | double area = 0.0; 52 | area = 0.5 * ( f(start) + f(end) ); 53 | double x = 0.0; 54 | for(x = start + delta; x <= end; x+= delta) 55 | { 56 | area += f(x); 57 | } 58 | area = area * delta; 59 | return area; 60 | } 61 | 62 | /* Function to be executed by the master rank */ 63 | void master(Params * p) 64 | { 65 | double last = 0.0; 66 | double area = p->error+1,local; 67 | double start, end; 68 | /* Loop until the difference of results is less than the error */ 69 | while(fabs(last - area) > p->error) 70 | { 71 | last = area; 72 | /* Start the clock */ 73 | start = MPI_Wtime(); 74 | /* Broadcast the intervals */ 75 | MPI_Bcast(&p->intervals,1,MPI_INT,0,MPI_COMM_WORLD); 76 | /* Reduce the result */ 77 | MPI_Reduce(&local,&area,1,MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); 78 | /* Stop the clock */ 79 | end = MPI_Wtime(); 80 | /* Calculate delta */ 81 | p->delta = (p->max-p->min)/p->intervals; 82 | /* Print results */ 83 | fprintf(stderr,"Intervals = %8d\tDelta = %f\tResult = %f\tError=%f\tTime = %f\n",p->intervals,p->delta,area,fabs(last-area),end-start); 84 | /* Double the number of intervals */ 85 | p->intervals = p->intervals*2; 86 | } 87 | /* Send all ranks term signal */ 88 | p->intervals = -1; 89 | MPI_Bcast(&p->intervals,1,MPI_INT,0,MPI_COMM_WORLD); 90 | return; 91 | } 92 | 93 | /* Function to be executed by all the slaves */ 94 | void slave(Params *p) 95 | { 96 | double start, end, area; 97 | /* Loop until done */ 98 | while(1) 99 | { 100 | /* Receive the interval count */ 101 | MPI_Bcast(&p->intervals,1,MPI_INT,0,MPI_COMM_WORLD); 102 | /* Terminate if no more work to do */ 103 | if(p->intervals == -1) 104 | return; 105 | /* Calculate the region */ 106 | p->region = (p->max-p->min)/(double)p->size; 107 | /* Calculate start of region */ 108 | start = p->min + p->region * (p->rank-1); 109 | /* Calculate end of region */ 110 | end = start + p->region; 111 | /* Calculate step (delta) */ 112 | p->delta = (p->max-p->min)/p->intervals; 113 | /* Use either the trapezoid or rectangle rule */ 114 | area = p->func(start,end,p->delta); 115 | /* Return results */ 116 | MPI_Reduce(&area,&area,1,MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); 117 | } 118 | } 119 | 120 | void usage() 121 | { 122 | printf("integration\n\ 123 | MPI Program to approximate an integral.\n\ 124 | Jharrod LaFon 2011\n\ 125 | Usage: integration [args]\n\ 126 | a \t\tStarting point of interval to be integrated\n\ 127 | b \t\tEnding point of interval to be integrated\n\ 128 | e \t\tMaximum error threshold\n\ 129 | t\t\tUse the trapezoid rule\n\ 130 | r\t\tUse the rectangle rule\n\ 131 | h\t\tPrint this message\n"); 132 | } 133 | 134 | /* Parse user arguments */ 135 | void parse_args(int argc, char ** argv, Params * p) 136 | { 137 | int c = 0; 138 | while((c = getopt(argc,argv,"a:b:e:trh")) != -1) 139 | { 140 | switch(c) 141 | { 142 | case 'a': 143 | p->min = atof(optarg); 144 | break; 145 | case 'b': 146 | p->max = atof(optarg); 147 | break; 148 | case 'e': 149 | p->error = atof(optarg); 150 | break; 151 | case 't': 152 | p->func = trapezoid_rule; 153 | break; 154 | case 'r': 155 | p->func = rectangle_rule; 156 | break; 157 | case 'h': 158 | if(p->rank == 0) usage(); 159 | exit(0); 160 | default: 161 | break; 162 | } 163 | } 164 | return; 165 | } 166 | 167 | /* Main */ 168 | int main(int argc, char *argv[]) 169 | { 170 | int rank; 171 | int size; 172 | /* Initialize MPI */ 173 | if(MPI_Init(&argc, &argv) != MPI_SUCCESS) 174 | { 175 | fprintf(stderr, "Unable to initialize MPI!\n"); 176 | return -1; 177 | } 178 | /* Get rank and size */ 179 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); 180 | MPI_Comm_size(MPI_COMM_WORLD, &size); 181 | 182 | /* Populate the parameters with default values */ 183 | Params p; 184 | p.min = INTERVAL_MIN; 185 | p.max = INTERVAL_MAX; 186 | p.error = ERROR_THRESHOLD; 187 | p.intervals = NUM_INTERVALS; 188 | p.rank = rank; 189 | p.size = size-1; 190 | p.func = rectangle_rule; 191 | 192 | /* Check for user options */ 193 | parse_args(argc,argv,&p); 194 | 195 | if(rank == 0) 196 | master(&p); 197 | else 198 | slave(&p); 199 | MPI_Finalize(); 200 | return 0; 201 | } 202 | -------------------------------------------------------------------------------- /mandelbrot/Makefile: -------------------------------------------------------------------------------- 1 | CC = mpicc 2 | LDFLAGS = -lX11 -lm 3 | 4 | mandelbrot: mandelbrot.c 5 | $(CC) $(LDFLAGS) mandelbrot.c -o mandelbrot 6 | 7 | mandel_bitmap: mandel_bitmap.c 8 | $(CC) $(LDFLAGS) mandel_bitmap.c -o mandel_bitmap 9 | 10 | image_manip_serial: image_manip_serial.c 11 | $(CC) $(LDFLAGS) image_manip_serial.c -o image_manip_serial 12 | 13 | clean: 14 | rm *.o mandelbrot image_manip_serial mandel_bitmap 15 | -------------------------------------------------------------------------------- /mandelbrot/mandel_bitmap.c: -------------------------------------------------------------------------------- 1 | /* File: mandelbrot.c 2 | Modified by: Jharrod LaFon 3 | Date: Spring 2011 4 | Purpose: Compute and display the Mandelbrot set 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #define X_RESN 15000 /* x resolution */ 14 | #define Y_RESN 10000 /* y resolution */ 15 | #define M_MAX 1048576 /* Max iterations for Mandelbrot */ 16 | // BITMAP header 17 | #pragma pack(push, 1) 18 | typedef struct 19 | { 20 | uint16_t type; 21 | uint32_t size; 22 | uint16_t reserved1, reserved2; 23 | uint32_t offset; 24 | } HEADER; 25 | #pragma pack(pop) 26 | 27 | 28 | // BITMAP information header 29 | #pragma pack(push, 1) 30 | typedef struct 31 | { 32 | uint32_t size; 33 | int32_t width, height; 34 | uint16_t planes; 35 | uint16_t bits; 36 | uint32_t compression; 37 | uint32_t isize; 38 | int32_t xres,yres; 39 | uint32_t colors; 40 | uint32_t impcolors; 41 | } IHEADER; 42 | #pragma pack(pop) 43 | 44 | // Pixel 45 | #pragma pack(push, 1) 46 | typedef struct Pixel 47 | { 48 | uint8_t b,g,r; 49 | } Pixel; 50 | #pragma pack(pop) 51 | 52 | // Struct to hold info on a bitmap 53 | #pragma pack(push, 1) 54 | typedef struct 55 | { 56 | HEADER header; 57 | IHEADER iheader; 58 | Pixel ** array; 59 | } BMP; 60 | #pragma pack(pop) 61 | int get_bmp_header(FILE * fp, BMP * img) 62 | { 63 | if(sizeof((*img).header) != fread(&(*img).header,1,sizeof((*img).header),fp)) 64 | { 65 | perror("Unable to read file"); 66 | exit(1); 67 | } 68 | if(sizeof((*img).iheader) != fread(&(*img).iheader,1,sizeof((*img).iheader),fp)) 69 | { 70 | perror("Unable to read file"); 71 | exit(1); 72 | } 73 | if((*img).header.type != 0x4D42) 74 | { 75 | printf("Error: Not a valid bitmap file.\n"); 76 | exit(1); 77 | } 78 | return 0; 79 | } 80 | 81 | 82 | int print_bmp_attr(BMP * bmp) 83 | { 84 | int linebits = (*bmp).iheader.width * (*bmp).iheader.bits; 85 | int linebytes = ((linebits + 31)/32)*4; 86 | printf("File: \n\t\ 87 | Linebytes: %d\n\t\ 88 | Type: %X\n\t\ 89 | Size: %d\n\t\ 90 | Offset: %d\n\t\ 91 | Size: %d\n\t\ 92 | Res1: %d\n\t\ 93 | Res2: %d\n\t\ 94 | Width: %d\n\t\ 95 | Height: %d\n\t\ 96 | Image Size: %u\n\t\ 97 | Xres: %u\n\t\ 98 | Yres: %u\n\t\ 99 | Planes: %u\n\t\ 100 | Bits/Pixel: %u\n\t\ 101 | Compression: %u\n\t\ 102 | Number of colors: %u\n\t\ 103 | Important colors: %u\n", linebytes,(*bmp).header.type, (*bmp).header.size, (*bmp).header.offset,(*bmp).iheader.size,(*bmp).header.reserved1,(*bmp).header.reserved2,(*bmp).iheader.width,(*bmp).iheader.height,(*bmp).iheader.isize, 104 | (*bmp).iheader.xres, (*bmp).iheader.yres,(*bmp).iheader.planes,(*bmp).iheader.bits, (*bmp).iheader.compression,(*bmp).iheader.colors,(*bmp).iheader.impcolors); 105 | return 0; 106 | } 107 | 108 | 109 | typedef struct complextype 110 | { 111 | float real, imag; 112 | } Compl; 113 | 114 | typedef enum { DATA_TAG, TERM_TAG, RESULT_TAG} Tags; 115 | 116 | Pixel cal_pixel(Compl c,int size,int rank) 117 | { 118 | Pixel result; 119 | uint64_t count; 120 | uint64_t colors = 0xFFFFFF / M_MAX; 121 | int rcolors = 0xFF / size; 122 | Compl z; 123 | float temp, lengthsq; 124 | z.real = 0; z.imag = 0; 125 | count = 0; 126 | do 127 | { 128 | temp = z.real * z.real - z.imag * z.imag + c.real; 129 | z.imag = 2 * z.real * z.imag + c.imag; 130 | z.real = temp; 131 | lengthsq = z.real * z.real + z.imag * z.imag; 132 | count++; 133 | } while((lengthsq < 4.0) && (count < M_MAX)); 134 | result.b = rank*count*colors & 0xFF; 135 | result.g = rank*count*colors; 136 | //result.r = z.real 137 | //result.r = rank*rcolors & 0xFF0000; 138 | result.r = rank*colors % count; 139 | return result; 140 | } 141 | void worker(int linebytes) 142 | { 143 | Pixel * colors = malloc(linebytes); 144 | MPI_Status status; 145 | int row,x,rank, size; 146 | MPI_Comm_size(MPI_COMM_WORLD,&size); 147 | MPI_Comm_rank(MPI_COMM_WORLD,&rank); 148 | MPI_Recv(&row , 1 , MPI_INT, 0, MPI_ANY_TAG, MPI_COMM_WORLD, &status); 149 | Compl c; 150 | Pixel xp; 151 | while(status.MPI_TAG != TERM_TAG) 152 | { 153 | c.imag = ((float)row-5500)/3500.0; 154 | for(x = 0; x < linebytes/3; x++) 155 | { 156 | c.real = ((float) x-8000)/3500.0; 157 | colors[x] = cal_pixel(c,rank,size); 158 | } 159 | MPI_Send(&colors[0], linebytes, MPI_BYTE, 0, row,MPI_COMM_WORLD); 160 | // fprintf(stderr,"Worker: %d Row: %d\n",rank,row); 161 | MPI_Recv(&row , 1 , MPI_INT, 0, MPI_ANY_TAG, MPI_COMM_WORLD, &status); 162 | 163 | } 164 | } 165 | 166 | int main (int argc, char **argv) 167 | { 168 | int rank, size; 169 | if(MPI_Init(&argc,&argv) != MPI_SUCCESS) 170 | { 171 | perror("Unable to initialize MPI\n"); 172 | exit(1); 173 | } 174 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); 175 | MPI_Comm_size(MPI_COMM_WORLD, &size); 176 | 177 | BMP bmp; 178 | //block 179 | bmp.header.type = 0x4D42; 180 | bmp.iheader.xres = bmp.iheader.yres = 3780; 181 | bmp.header.reserved1 = bmp.header.reserved2 = 0; 182 | bmp.iheader.size = 40; 183 | bmp.iheader.compression = 0; 184 | bmp.iheader.width = X_RESN; 185 | bmp.iheader.bits = 24; 186 | bmp.iheader.colors = 0; 187 | bmp.iheader.impcolors = 0; 188 | bmp.iheader.height = Y_RESN; 189 | //block 190 | FILE * fp = 0; 191 | if((fp = fopen("dot.bmp","r+")) == NULL) 192 | { 193 | perror("Cannot create file"); 194 | exit(1); 195 | } 196 | // get_bmp_header(fp,&bmp); 197 | int linebits = bmp.iheader.width * bmp.iheader.bits; 198 | int linebytes = ((linebits + 31)/32)*4; 199 | if(rank != 0) 200 | worker(linebytes); 201 | else 202 | { 203 | //block 204 | bmp.iheader.planes = 1; 205 | bmp.iheader.isize = linebytes * bmp.iheader.height; 206 | bmp.header.offset = 54; 207 | bmp.header.size = bmp.header.offset + bmp.iheader.isize; 208 | //block 209 | print_bmp_attr(&bmp); 210 | 211 | fseek(fp,0,SEEK_SET); 212 | fwrite(&bmp.header,1,sizeof(bmp.header),fp); 213 | fwrite(&bmp.iheader,1,sizeof(bmp.iheader),fp); 214 | int k, count, row,column,byte; 215 | Pixel * current; 216 | Pixel ** newimg = malloc(sizeof(Pixel*) * bmp.iheader.height); 217 | for(row = bmp.iheader.height-1; row >= 0; row--) 218 | { 219 | current = (Pixel *) malloc(linebytes); 220 | column = 0; 221 | for(byte = 0; byte < linebytes; byte+=3) 222 | { 223 | fread(¤t[column++],1,sizeof(Pixel),fp); 224 | } 225 | newimg[row] = current; 226 | fseek(fp, bmp.header.offset + (bmp.iheader.height-1-row) * linebytes, SEEK_SET); 227 | } 228 | fclose(fp); 229 | /* Mandlebrot variables */ 230 | 231 | bmp.array = newimg; 232 | Pixel * colors; 233 | count = 0; 234 | row = 0; 235 | for(k = 1; k < size; k++) 236 | { 237 | MPI_Send(&row, 1, MPI_INT, k, DATA_TAG,MPI_COMM_WORLD); 238 | count++; 239 | row++; 240 | } 241 | // memset(colors,0,linebytes); 242 | double start, end; 243 | MPI_Status status; 244 | start = MPI_Wtime(); 245 | do 246 | { 247 | 248 | colors = (Pixel *) malloc(linebytes * sizeof(Pixel)); 249 | MPI_Recv(&colors[0] , linebytes , MPI_BYTE, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status); 250 | end = MPI_Wtime(); 251 | fprintf(stderr,"[%d] Recv'd row: %d from %d. Count = %d, row = %d %f s/row %f left\n", 252 | rank,status.MPI_TAG, status.MPI_SOURCE,count,row, (end-start)/(double)row, (end-start)/(double)row*(bmp.iheader.height-row)); 253 | count--; 254 | if(row < bmp.iheader.height) 255 | { 256 | MPI_Send(&row, 1, MPI_INT, status.MPI_SOURCE, DATA_TAG, MPI_COMM_WORLD); 257 | row++; 258 | count++; 259 | } 260 | else 261 | MPI_Send(&k, 1, MPI_INT, status.MPI_SOURCE, TERM_TAG, MPI_COMM_WORLD); 262 | newimg[status.MPI_TAG] = colors; 263 | } 264 | while(count > 0); 265 | /* Program Finished */ 266 | fprintf(stderr,"Received %d rows\n", row); 267 | if((fp = fopen("dot.bmp","r+")) == NULL) 268 | { 269 | perror("Cannot create file"); 270 | exit(1); 271 | } 272 | if(fseek(fp,bmp.header.offset,SEEK_SET) != 0) 273 | perror("seek"); 274 | 275 | for(row = bmp.iheader.height-1; row >= 0; row--) 276 | { 277 | if(fwrite(&newimg[row][0],1,linebytes,fp) == 0) 278 | perror("fwrite"); 279 | } 280 | fclose(fp); 281 | } 282 | MPI_Barrier(MPI_COMM_WORLD); 283 | MPI_Finalize(); 284 | return 0; 285 | } 286 | 287 | -------------------------------------------------------------------------------- /mandelbrot/mandelbrot.c: -------------------------------------------------------------------------------- 1 | /* File: mandelbrot.c 2 | Modified by: Jharrod LaFon 3 | Date: Spring 2011 4 | Purpose: Compute and display the Mandelbrot set 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #define X_RESN 1024 /* x resolution */ 17 | #define Y_RESN 1024 /* y resolution */ 18 | #define M_MAX (1 << 24) /* Max iterations for Mandelbrot */ 19 | // BITMAP header 20 | #pragma pack(push, 1) 21 | typedef struct 22 | { 23 | uint16_t type; 24 | uint32_t size; 25 | uint16_t reserved1, reserved2; 26 | uint32_t offset; 27 | } HEADER; 28 | #pragma pack(pop) 29 | 30 | // BITMAP information header 31 | #pragma pack(push, 1) 32 | typedef struct 33 | { 34 | uint32_t size; 35 | int32_t width, height; 36 | uint16_t planes; 37 | uint16_t bits; 38 | uint32_t compression; 39 | uint32_t isize; 40 | int32_t xres,yres; 41 | uint32_t colors; 42 | uint32_t impcolors; 43 | } IHEADER; 44 | #pragma pack(pop) 45 | 46 | // Pixel 47 | #pragma pack(push, 1) 48 | typedef struct Pixel 49 | { 50 | uint8_t b,g,r; 51 | } Pixel; 52 | #pragma pack(pop) 53 | 54 | // Struct to hold info on a bitmap 55 | #pragma pack(push, 1) 56 | typedef struct 57 | { 58 | HEADER header; 59 | IHEADER iheader; 60 | Pixel ** array; 61 | } BMP; 62 | #pragma pack(pop) 63 | 64 | 65 | typedef struct complextype 66 | { 67 | float real, imag; 68 | } Compl; 69 | typedef struct Xstuff 70 | { 71 | Window * win; 72 | Display * display; 73 | GC * gc; 74 | } Xstuff; 75 | 76 | typedef enum { DATA_TAG, TERM_TAG, RESULT_TAG} Tags; 77 | 78 | int cal_pixel(Compl c) 79 | { 80 | int count; 81 | Compl z; 82 | float temp, lengthsq; 83 | z.real = 0; z.imag = 0; 84 | count = 0; 85 | do 86 | { 87 | temp = z.real * z.real - z.imag * z.imag + c.real; 88 | z.imag = 2 * z.real * z.imag + c.imag; 89 | z.real = temp; 90 | lengthsq = z.real * z.real + z.imag * z.imag; 91 | count++; 92 | } while((lengthsq < 4.0) && (count < M_MAX)); 93 | return count; 94 | } 95 | 96 | void draw_row(Xstuff * session, int row,int * colors) 97 | { 98 | int j = 0; 99 | for(j=0; j < Y_RESN; j++) 100 | if (colors[j] == 100) 101 | XDrawPoint (session->display, *session->win, *session->gc, j, row); 102 | 103 | } 104 | 105 | void worker() 106 | { 107 | int * colors = malloc(sizeof(int) * (X_RESN+1)); 108 | MPI_Status status; 109 | int row,x,rank; 110 | MPI_Comm_rank(MPI_COMM_WORLD,&rank); 111 | MPI_Recv(&row , 1 , MPI_INT, 0, MPI_ANY_TAG, MPI_COMM_WORLD, &status); 112 | Compl c; 113 | while(status.MPI_TAG == DATA_TAG) 114 | { 115 | colors[0] = row; 116 | c.imag = ((float)row - 400.0)/200.0; 117 | for(x = 0; x < X_RESN; x++) 118 | { 119 | c.real = ((float) x - 400.0)/200.0; 120 | colors[x+1] = cal_pixel(c); 121 | } 122 | MPI_Send(&colors[0], X_RESN, MPI_INT, 0, RESULT_TAG,MPI_COMM_WORLD); 123 | MPI_Recv(&row , 1 , MPI_INT, 0, MPI_ANY_TAG, MPI_COMM_WORLD, &status); 124 | 125 | } 126 | } 127 | 128 | int main (int argc, char **argv) 129 | { 130 | int rank, size; 131 | if(MPI_Init(&argc,&argv) != MPI_SUCCESS) 132 | { 133 | perror("Unable to initialize MPI\n"); 134 | exit(1); 135 | } 136 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); 137 | MPI_Comm_size(MPI_COMM_WORLD, &size); 138 | 139 | if(rank != 0) 140 | worker(); 141 | else 142 | { 143 | 144 | Window win; /* initialization for a window */ 145 | unsigned 146 | int width, height, /* window size */ 147 | x, y, /* window position */ 148 | border_width, /*border width in pixels */ 149 | display_width, display_height, /* size of screen */ 150 | screen; /* which screen */ 151 | 152 | char *window_name = "Mandelbrot Set", *display_name = NULL; 153 | GC gc; 154 | unsigned 155 | long valuemask = 0; 156 | XGCValues values; 157 | Display *display; 158 | XSizeHints size_hints; 159 | Xstuff session; 160 | // Pixmap bitmap; 161 | // XPoint points[800]; 162 | // FILE *fp, *fopen (); 163 | // char str[100]; 164 | 165 | XSetWindowAttributes attr[1]; 166 | 167 | 168 | /* connect to Xserver */ 169 | 170 | if ( (display = XOpenDisplay (display_name)) == NULL ) { 171 | fprintf (stderr, "drawon: cannot connect to X server %s\n", 172 | XDisplayName (display_name) ); 173 | exit (-1); 174 | } 175 | 176 | /* get screen size */ 177 | 178 | screen = DefaultScreen (display); 179 | display_width = DisplayWidth (display, screen); 180 | display_height = DisplayHeight (display, screen); 181 | 182 | /* set window size */ 183 | 184 | width = X_RESN; 185 | height = Y_RESN; 186 | 187 | /* set window position */ 188 | 189 | x = 0; 190 | y = 0; 191 | 192 | /* create opaque window */ 193 | 194 | border_width = 4; 195 | win = XCreateSimpleWindow (display, RootWindow (display, screen), 196 | x, y, width, height, border_width, 197 | BlackPixel (display, screen), WhitePixel (display, screen)); 198 | 199 | size_hints.flags = USPosition|USSize; 200 | size_hints.x = x; 201 | size_hints.y = y; 202 | size_hints.width = width; 203 | size_hints.height = height; 204 | size_hints.min_width = 300; 205 | size_hints.min_height = 300; 206 | 207 | XSetNormalHints (display, win, &size_hints); 208 | XStoreName(display, win, window_name); 209 | 210 | /* create graphics context */ 211 | 212 | gc = XCreateGC (display, win, valuemask, &values); 213 | 214 | XSetBackground (display, gc, WhitePixel (display, screen)); 215 | XSetForeground (display, gc, BlackPixel (display, screen)); 216 | XSetLineAttributes (display, gc, 1, LineSolid, CapRound, JoinRound); 217 | 218 | attr[0].backing_store = Always; 219 | attr[0].backing_planes = 1; 220 | attr[0].backing_pixel = BlackPixel(display, screen); 221 | 222 | XChangeWindowAttributes(display, win, CWBackingStore | CWBackingPlanes | CWBackingPixel, attr); 223 | 224 | XMapWindow (display, win); 225 | XSync(display, 0); 226 | session.gc = &gc; 227 | session.win = &win; 228 | session.display = display; 229 | 230 | /* Mandlebrot variables */ 231 | int k, count, row; 232 | 233 | 234 | count = 0; 235 | row = 0; 236 | for(k = 1; k < size; k++) 237 | { 238 | MPI_Send(&row, 1, MPI_INT, k, DATA_TAG,MPI_COMM_WORLD); 239 | count++; 240 | row++; 241 | } 242 | int * colors = (int *) malloc(sizeof(int) * (X_RESN+1)); 243 | MPI_Status status; 244 | do 245 | { 246 | MPI_Recv(&colors[0] , X_RESN , MPI_INT, MPI_ANY_SOURCE, RESULT_TAG, MPI_COMM_WORLD, &status); 247 | count--; 248 | if(row < X_RESN) 249 | { 250 | MPI_Send(&row, 1, MPI_INT, status.MPI_SOURCE, DATA_TAG, MPI_COMM_WORLD); 251 | row++; 252 | count++; 253 | } 254 | else 255 | MPI_Send(&row, 1, MPI_INT, status.MPI_SOURCE, TERM_TAG, MPI_COMM_WORLD); 256 | draw_row(&session,colors[0],&colors[1]); 257 | } 258 | while(count > 0); 259 | printf("\n"); 260 | XFlush (display); 261 | sleep (10); 262 | /* Program Finished */ 263 | 264 | } 265 | MPI_Barrier(MPI_COMM_WORLD); 266 | MPI_Finalize(); 267 | return 0; 268 | } 269 | 270 | -------------------------------------------------------------------------------- /matrix-multipy/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | LDFLAGS = -lrt 3 | 4 | main: main.c 5 | $(CC) -c main.c 6 | 7 | linux: main.o 8 | $(CC) $(LDFLAGS) main.o -o mm 9 | 10 | solaris: main.o 11 | $(CC) $(LDFLAGS) main.o -o mm_solaris 12 | 13 | clean: 14 | rm *.o mm mm_solaris 15 | -------------------------------------------------------------------------------- /matrix-multipy/README: -------------------------------------------------------------------------------- 1 | File: README 2 | Author: Jharrod LaFon 3 | Date: Fall 2010 4 | 5 | Contents 6 | -------- 7 | I. Compiling 8 | II. Usage 9 | III. Theory of Operation 10 | 11 | I. Compiling 12 | ------------ 13 | For GNU/Linux based systems, run: 14 | `make linux` 15 | The resulting binary will be called `mm` 16 | 17 | For Solaris (Unix) systems, run: 18 | `make solaris` 19 | The resulting binary will be called `mm_solaris` 20 | 21 | II. Usage 22 | --------- 23 | For Linux based systems, run: 24 | `./mm` 25 | You will see this output: 26 | Usage: mm -n