void compute_wedge_y(Grid* A, Grid* B, int x, int y, int s) { assert(s > 0); if (s <= CUT_OFF) { // compute height of wedge int h = (s + 1) / 2; if (DEBUG) printf("Computing wedge %d/%d/%d/Y ...\n", x, y, s); // just compute the wedge for(int l=0; l<h; l++) { // compute one plain of the pyramid for(int i = x-l; i<=x+l; i++) { //printf("Level %d - bounds x: %d,%d - bounds y: %d,%d\n", h, x-l, x+l, y-(h-l)+1, y+(h-l)-1 ); for(int j = y-(h-l)+1; j<=y+(h-l)-1; j++) { update(A,B,i,j); } } // switch plains Grid* C = A; A = B; B = C; } return; } if (DEBUG) printf("Decomposing wedge %d/%d/%d/Y ...\n", x, y, s); // decompose into 2 pyramids and 4 wedges // compute coordinates offset of sub-wedges int d = (s-1)/2; int h = (d+1)/2; // compute bottom wedges (parallel) #pragma omp task compute_wedge_y(A, B, x, y-h, d); #pragma omp task compute_wedge_y(A, B, x, y+h, d); #pragma omp taskwait // reverse pyramid compute_reverse(A, B, x, y, d); // compute pyramid on top compute_pyramid(A, B, x, y, d); // compute remaining two wedges (parallel) #pragma omp task compute_wedge_y(A, B, x-h, y, d); #pragma omp task compute_wedge_y(A, B, x+h, y, d); #pragma omp taskwait }
void jacobi_recursive(Grid* A, Grid* B, int num_iter) { #pragma omp parallel { #pragma omp single { // compute full pyramid if (DEBUG) printf("\nProcessing main pyramid ...\n"); compute_pyramid(A, B, N/2, N/2, N-2); if (DEBUG) printf("\nProcessing x wedge ...\n"); compute_wedge_x(A, B, N/2,0, N-2); if (DEBUG) printf("\nProcessing y wedge ...\n"); compute_wedge_y(A, B, 0, N/2, N-2); if (DEBUG) printf("\nProcessing reverse pyramid ...\n"); compute_reverse(A, B, 0, 0, N-2); } } }
static void _prepare_sized_pattern(mbe_t *mbe, mbe_pattern_t *ptn) { SkCanvas *canvas = mbe->canvas; SkPath path; co_aix x, y; co_aix reverse[6]; *mbe->saved_region = canvas->getTotalClip(); compute_reverse(ptn->matrix, reverse); x = 0; y = 0; matrix_trans_pos(reverse, &x, &y); path.moveTo(CO_AIX_2_SKSCALAR(x), CO_AIX_2_SKSCALAR(y)); x = 0; y = ptn->h; matrix_trans_pos(reverse, &x, &y); path.moveTo(CO_AIX_2_SKSCALAR(x), CO_AIX_2_SKSCALAR(y)); x = ptn->w; y = ptn->h; matrix_trans_pos(reverse, &x, &y); path.moveTo(CO_AIX_2_SKSCALAR(x), CO_AIX_2_SKSCALAR(y)); path.close(); canvas->clipPath(path, SkRegion::kIntersect_Op); }
void compute_reverse(Grid* A, Grid* B, int x, int y, int s) { assert(s % 2 == 1 && "Only odd sizes are supported!"); // check for terminal case if (s <= CUT_OFF) { // compute height of pyramid int h = (s + 1) / 2; if (DEBUG) printf("Computing reverse pyramid at (%d,%d) with size %d ...\n", x, y, s); // just compute the pyramid for(int l=0; l<h; l++) { // compute one plain of the pyramid for(int i = x-l; i<=x+l; i++) { for(int j = y-l; j<=y+l; j++) { update(A,B,i,j); } } // switch plains Grid* C = A; A = B; B = C; } // done return; } if (DEBUG) printf("Decomposing reverse pyramid at (%d,%d) with size %d ...\n", x, y, s); // cut into 6 smaller pyramids + 4 wedges // compute size of pyramids int d = (s-1)/2; int h = (d+1)/2; int ux = x - h; int lx = x + h; int uy = y - h; int ly = y + h; // compute tip compute_reverse(A, B, x, y, d); // compute reverse pyramid in the center compute_pyramid(A, B, x, y, d); // compute 4 wedges (parallel) #pragma omp task compute_wedge_y(A, B, ux, y, d); #pragma omp task compute_wedge_y(A, B, lx, y, d); #pragma omp task compute_wedge_x(A, B, x, uy, d); #pragma omp task compute_wedge_x(A, B, x, ly, d); #pragma omp taskwait // compute 4 base-pyramids (parallel) #pragma omp task compute_reverse(A, B, lx, ly, d); #pragma omp task compute_reverse(A, B, lx, uy, d); #pragma omp task compute_reverse(A, B, ux, ly, d); #pragma omp task compute_reverse(A, B, ux, uy, d); #pragma omp taskwait }