Alien-FreeImage

 view release on metacpan or  search on metacpan

src/Source/FreeImageToolkit/MultigridPoissonSolver.cpp  view on Meta::CPAN

	const float *uc_bits = (float*)FreeImage_GetBits(UC);
	
	// do elements that are copies
	{
		const int nc = nf/2 + 1;

		float *uf_scan = uf_bits;
		const float *uc_scan = uc_bits;		
		for (row_uc = 0; row_uc < nc; row_uc++) {
			for (col_uc = 0, col_uf = 0; col_uc < nc; col_uc++, col_uf += 2) {
				// calculate UF(2*row_uc, col_uf) = UC(row_uc, col_uc);
				uf_scan[col_uf] = uc_scan[col_uc];
			}
			uc_scan += uc_pitch;
			uf_scan += 2 * uf_pitch;
		}
	}
	// do odd-numbered columns, interpolating vertically
	{		
		for(row_uf = 1; row_uf < nf-1; row_uf += 2) {
			float *uf_scan = uf_bits + row_uf * uf_pitch;
			for (col_uf = 0; col_uf < nf; col_uf += 2) {
				// calculate UF(row_uf, col_uf) = 0.5 * ( UF(row_uf+1, col_uf) + UF(row_uf-1, col_uf) )
				uf_scan[col_uf] = 0.5F * ( *(uf_scan + uf_pitch + col_uf) + *(uf_scan - uf_pitch + col_uf) );
			}
		}
	}
	// do even-numbered columns, interpolating horizontally
	{
		float *uf_scan = uf_bits;
		for(row_uf = 0; row_uf < nf; row_uf++) {
			for (col_uf = 1; col_uf < nf-1; col_uf += 2) {
				// calculate UF(row_uf, col_uf) = 0.5 * ( UF(row_uf, col_uf+1) + UF(row_uf, col_uf-1) )
				uf_scan[col_uf] = 0.5F * ( uf_scan[col_uf + 1] + uf_scan[col_uf - 1] );
			}
			uf_scan += uf_pitch;
		}
	}
}

/**
Red-black Gauss-Seidel relaxation for model problem. Updates the current value of the solution
u[0..n-1][0..n-1], using the right-hand side function rhs[0..n-1][0..n-1].
*/
static void fmg_relaxation(FIBITMAP *U, FIBITMAP *RHS, int n) {
	int row, col, ipass, isw, jsw;
	const float h = 1.0F / (n - 1);
	const float h2 = h*h;

	const int u_pitch  = FreeImage_GetPitch(U) / sizeof(float);
	const int rhs_pitch  = FreeImage_GetPitch(RHS) / sizeof(float);
	
	float *u_bits = (float*)FreeImage_GetBits(U);
	const float *rhs_bits = (float*)FreeImage_GetBits(RHS);

	for (ipass = 0, jsw = 1; ipass < 2; ipass++, jsw = 3-jsw) { // Red and black sweeps
		float *u_scan = u_bits + u_pitch;
		const float *rhs_scan = rhs_bits + rhs_pitch;
		for (row = 1, isw = jsw; row < n-1; row++, isw = 3-isw) {
			for (col = isw; col < n-1; col += 2) { 
				// Gauss-Seidel formula
				// calculate U(row, col) = 
				// 0.25 * [ U(row+1, col) + U(row-1, col) + U(row, col+1) + U(row, col-1) - h2 * RHS(row, col) ]		 
				float *u_center = u_scan + col;
				const float *rhs_center = rhs_scan + col;
				*u_center = *(u_center + u_pitch) + *(u_center - u_pitch) + *(u_center + 1) + *(u_center - 1);
				*u_center -= h2 * *rhs_center;
				*u_center *= 0.25F;
			}
			u_scan += u_pitch;
			rhs_scan += rhs_pitch;
		}
	}
}

/**
Returns minus the residual for the model problem. Input quantities are u[0..n-1][0..n-1] and
rhs[0..n-1][0..n-1], while res[0..n-1][0..n-1] is returned.
*/
static void fmg_residual(FIBITMAP *RES, FIBITMAP *U, FIBITMAP *RHS, int n) {
	int row, col;

	const float h = 1.0F / (n-1);	
	const float h2i = 1.0F / (h*h);

	const int res_pitch  = FreeImage_GetPitch(RES) / sizeof(float);
	const int u_pitch  = FreeImage_GetPitch(U) / sizeof(float);
	const int rhs_pitch  = FreeImage_GetPitch(RHS) / sizeof(float);
	
	float *res_bits = (float*)FreeImage_GetBits(RES);
	const float *u_bits = (float*)FreeImage_GetBits(U);
	const float *rhs_bits = (float*)FreeImage_GetBits(RHS);

	// interior points
	{
		float *res_scan = res_bits + res_pitch;
		const float *u_scan = u_bits + u_pitch;
		const float *rhs_scan = rhs_bits + rhs_pitch;
		for (row = 1; row < n-1; row++) {
			for (col = 1; col < n-1; col++) {
				// calculate RES(row, col) = 
				// -h2i * [ U(row+1, col) + U(row-1, col) + U(row, col+1) + U(row, col-1) - 4 * U(row, col) ] + RHS(row, col);
				float *res_center = res_scan + col;
				const float *u_center = u_scan + col;
				const float *rhs_center = rhs_scan + col;
				*res_center = *(u_center + u_pitch) + *(u_center - u_pitch) + *(u_center + 1) + *(u_center - 1) - 4 * *u_center;
				*res_center *= -h2i;
				*res_center += *rhs_center;
			}
			res_scan += res_pitch;
			u_scan += u_pitch;
			rhs_scan += rhs_pitch;
		}
	}

	// boundary points
	{
		memset(FreeImage_GetScanLine(RES, 0), 0, FreeImage_GetPitch(RES));
		memset(FreeImage_GetScanLine(RES, n-1), 0, FreeImage_GetPitch(RES));
		float *left = res_bits;
		float *right = res_bits + (n-1);



( run in 1.724 second using v1.01-cache-2.11-cpan-70e19b8f4f1 )