예제 #1
0
파일: finite_diff.c 프로젝트: mrirecon/bart
/*
 * Implements finite difference operator (order 1 for now)
 * using circular shift: diff(x) = x - circshift(x)
 * @param snip Keeps first entry if snip = false; clear first entry if snip = true
 *
 * optr = [iptr(1); diff(iptr)]
 */
static void md_zfinitediff_core2(unsigned int D, const long dims[D], unsigned int flags, bool snip, complex float* tmp, const long ostrs[D], complex float* optr, const long istrs[D], const complex float* iptr)
{
	md_copy2(D, dims, istrs, tmp, istrs, iptr, sizeof(complex float));

	long zdims[D];
	long center[D];

	md_select_dims(D, ~0, zdims, dims);
	memset(center, 0, D * sizeof(long));

	for (unsigned int i=0; i < D; i++) {
		if (MD_IS_SET(flags, i)) {
			center[i] = 1; // order

			md_circ_shift2(D, dims, center, ostrs, optr, istrs, tmp, sizeof(complex float));

			zdims[i] = 1;

			if (!snip) // zero out first dimension before subtracting
				md_clear2(D, zdims, ostrs, optr, sizeof(complex float));

			md_zsub2(D, dims, ostrs, optr, istrs, tmp, ostrs, optr);
			md_copy2(D, dims, ostrs, tmp, ostrs, optr, sizeof(complex float));

			if (snip) // zero out first dimension after subtracting
				md_clear2(D, zdims, ostrs, optr, sizeof(complex float));

			center[i] = 0;
			zdims[i] = dims[i];
		}
	}
}
예제 #2
0
파일: finite_diff.c 프로젝트: mrirecon/bart
/*
 * Adjoint of finite difference operator along specified dimensions.
 * Equivalent to finite difference in reverse order
 * 
 * @param snip if false: keeps the original value for the last entry;
 * if true: implements the adjoint of the difference matrix with all zero first row
 *
 * optr = [-diff(iptr); iptr(end)] = flip(fdiff_apply(flip(iptr)))
 */
static void fdiff_apply_adjoint(const linop_data_t* _data, complex float* optr, const complex float* iptr)
{
	const auto data = CAST_DOWN(fdiff_s, _data);

	md_copy2(data->D, data->dims, data->str, optr, data->str, iptr, CFL_SIZE);

	for (unsigned int i=0; i < data->D; i++) {

		unsigned int single_flag = data->flags & MD_BIT(i);

		if (single_flag) {

			complex float* tmp = md_alloc_sameplace(data->D, data->dims, CFL_SIZE, optr);
			complex float* tmp2 = md_alloc_sameplace(data->D, data->dims, CFL_SIZE, optr);
			md_flip2(data->D, data->dims, single_flag, data->str, tmp2, data->str, optr, CFL_SIZE);
			md_zfinitediff_core2(data->D, data->dims, single_flag, false, tmp, data->str, tmp2, data->str, tmp2);
			md_flip2(data->D, data->dims, single_flag, data->str, optr, data->str, tmp2, CFL_SIZE);

			md_free(tmp2);
			md_free(tmp);

			if (data->snip) {

				long zdims[data->D];
				md_select_dims(data->D, ~0, zdims, data->dims);

				zdims[i] = 1;
				md_zsub2(data->D, zdims, data->str, optr, data->str, optr, data->str, iptr);
			}
		}
	}
}
예제 #3
0
파일: sum.c 프로젝트: grlee77/bart
/**
 * 
 * x = (ATA + uI)^-1 b
 * 
 */
void sum_apply_pinverse(const void* _data, float rho, complex float* dst, const complex float* src)
{
	struct sum_data* data = (struct sum_data*) _data;

	if (NULL == data->tmp) {

#ifdef USE_CUDA
		data->tmp = (data->use_gpu ? md_alloc_gpu : md_alloc)(DIMS, data->img_dims, CFL_SIZE);
#else
		data->tmp = md_alloc(DIMS, data->img_dims, CFL_SIZE);
#endif
	}


	// get average
	md_clear( DIMS, data->img_dims, data->tmp, sizeof( complex float ) );

	md_zadd2( DIMS, data->imgd_dims, data->img_strs, data->tmp, data->img_strs, data->tmp , data->imgd_strs, src );
	md_zsmul( DIMS, data->img_dims, data->tmp, data->tmp, 1. / data->levels );


	// get non-average
	md_zsub2( DIMS, data->imgd_dims, data->imgd_strs, dst, data->imgd_strs, src, data->img_strs, data->tmp );

	// avg = avg / (1 + rho)
	md_zsmul( DIMS, data->img_dims, data->tmp, data->tmp, 1. / (1. + rho) );

	// nonavg = nonavg / rho
	md_zsmul( DIMS, data->imgd_dims, dst, dst, 1. / rho );

	// dst = avg + nonavg
	md_zadd2( DIMS, data->imgd_dims, data->imgd_strs, dst, data->imgd_strs, dst, data->img_strs, data->tmp );
}
예제 #4
0
파일: finite_diff.c 프로젝트: mrirecon/bart
// y = 2*x - circshift(x,center_adj) - circshift(x,center)
static void zfinitediff_normal(const linop_data_t* _data,
			complex float* optr, const complex float* iptr)
{
	const auto data = CAST_DOWN(zfinitediff_data, _data);

	// Turns out that this is faster, but this requires extra memory.
	complex float* tmp = md_alloc_sameplace(data->D, data->dims_in, CFL_SIZE, iptr);

	zfinitediff_apply(_data, tmp, iptr);
	zfinitediff_adjoint(_data, optr, tmp);

	md_free(tmp);
	return;		// FIXME: WTF?


	unsigned long d = data->dim_diff;
	long nx = data->dims_in[d];
	long offset;
	long dims_sub[data->D];
	md_copy_dims(data->D, dims_sub, data->dims_in);

	// optr and iptr same size regardless if do_circdiff true/false
	// if (data->do_circdiff)
	//    out = 2*in;
	//    out(..,1:(end-1),..) = out(..,1:(end-1),..) - in(..,2:end,..)
	//    out(..,2:end,..) = out(..,2:end,..) - in(..,1:(end-1),..)
	//    out(..,end,..) = out(..,end,..) - in(..,1,..)
	//    out(..,1,..) = out(..,1,..) - in(..,end,..)
	//
	// else
	//    out(..,1,..) = in(..,1,..)
	//    out(..,end,..) = in(..,end,..)
	//    out(..,2:(end-1),..) = 2*in(..,2:(end-1),..)
	//    out(..,1:(end-1),..) = out(..,1:(end-1),..) - in(..,2:end,..)
	//    out(..,2:end,..) = out(..,2:end,..) - in(..,1:(end-1),..)
	//

	if (data->do_circdiff) {

		md_zsmul2(data->D, data->dims_in, data->strides_in, optr,
				data->strides_in, iptr, 2.);

		dims_sub[d] = (nx - 1);
		offset = data->strides_in[d] / CFL_SIZE;
		// out(..,1:(end-1),..) = out(..,1:(end-1),..) - in(..,2:end,..)
		md_zsub2(data->D, dims_sub, data->strides_in, optr,
				data->strides_in, optr, data->strides_in, iptr + offset);
		// out(..,2:end,..) = out(..,2:end,..) - in(..,1:(end-1),..)
		md_zsub2(data->D, dims_sub, data->strides_in, optr + offset,
				data->strides_in, optr + offset, data->strides_in, iptr);

		dims_sub[d] = 1;
		offset = (nx - 1) * data->strides_in[d] / CFL_SIZE;
		// out(..,1,..) = out(..,1,..) - in(..,end,..)
		md_zsub2(data->D, dims_sub, data->strides_in, optr,
				data->strides_in, optr, data->strides_in, iptr + offset);
		// out(..,end,..) = out(..,end,..) - in(..,1,..)
		md_zsub2(data->D, dims_sub, data->strides_in, optr+offset,
				data->strides_in, optr+offset, data->strides_in, iptr);

	} else {

		dims_sub[d] = 1;
		offset = (nx - 1) * data->strides_in[d] / CFL_SIZE;
		// out(..,1,..) = in(..,1,..)
		md_copy2(data->D, dims_sub,
				data->strides_in, optr, data->strides_in, iptr, CFL_SIZE);
		// out(..,end,..) = in(..,end,..)
		md_copy2(data->D, dims_sub,
				data->strides_in, optr + offset, data->strides_in, iptr + offset,
				CFL_SIZE);

		dims_sub[d] = nx - 2;
		offset = data->strides_in[d] / CFL_SIZE;
		// out(..,2:(end-1),..) = 2*in(..,2:(end-1),..)
		md_zsmul2(data->D, dims_sub, data->strides_in, optr + offset,
				data->strides_in, iptr + offset, 2.);

		dims_sub[d] = nx - 1;
		offset = data->strides_in[d] / CFL_SIZE;
		// out(..,1:(end-1),..) = out(..,1:(end-1),..) - in(..,2:end,..)
		md_zsub2(data->D, dims_sub, data->strides_in, optr,
				data->strides_in, optr, data->strides_in, iptr + offset);
		// out(..,2:end,..) = out(..,2:end,..) - in(..,1:(end-1),..)
		md_zsub2(data->D, dims_sub, data->strides_in, optr + offset,
				data->strides_in, optr + offset, data->strides_in, iptr);

	}
}
예제 #5
0
파일: finite_diff.c 프로젝트: mrirecon/bart
static void zfinitediff_adjoint(const linop_data_t* _data,
			  complex float* optr, const complex float* iptr)
{
	const auto data = CAST_DOWN(zfinitediff_data, _data);

	// if (docircshift)
	//     out(..,2:end,..) = in(..,2:end,..) - in(..,1:(end-1),..)
	//     out(..,1,..) = in(..,1,..) - in(..,end,..)
	// else
	//     out(..,1,..) = in(..,1,..)
	//     out(..,2:(end-1),..) = in(..,2:end,..) - in(..,1:(end-1),..)
	//     out(..,end,..) = -in(..,end,..);

	unsigned int d = data->dim_diff;
	long nx = data->dims_adj[d];
	long off_in, off_adj;

	long dims_sub[data->D];
	md_copy_dims(data->D, dims_sub, data->dims_adj);

	if (data->do_circdiff) {

		// out(..,2:end,..) = in(..,2:end,..) - in(..,1:(end-1),..)
		dims_sub[d] = nx - 1;
		off_adj = data->strides_adj[d] / CFL_SIZE;
		off_in = data->strides_in[d] / CFL_SIZE;
		md_zsub2(data->D, dims_sub, data->strides_in, optr + off_in,
				data->strides_in, iptr + off_adj, data->strides_adj, iptr);

		// out(..,1,..) = in(..,1,..) - in(..,end,..)
		dims_sub[d] = 1;
		off_adj = (nx - 1) * data->strides_adj[d] / CFL_SIZE;
		off_in = (nx - 1) * data->strides_in[d] / CFL_SIZE;
		md_zsub2(data->D, dims_sub, data->strides_in, optr,
				data->strides_adj, iptr, data->strides_adj, iptr + off_adj);

	} else {

		// out(..,end,..) = 0
		//md_clear2(data->D, data->dims_in, data->strides_in, optr, CFL_SIZE);
		dims_sub[d] = 1;
		off_in = nx * data->strides_in[d] / CFL_SIZE;
		md_clear2(data->D, dims_sub, data->strides_in, optr + off_in, CFL_SIZE);
		// out(..,1:end-1,:) = in_adj(..,1:end,:)
		md_copy2(data->D, data->dims_adj, data->strides_in, optr,
				data->strides_adj, iptr, CFL_SIZE);
		// out(..,2:end,:) -= in_adj(..,1:end,:)
		off_in = data->strides_in[d] / CFL_SIZE;
		md_zsub2(data->D, data->dims_adj, data->strides_in, optr + off_in,
				data->strides_in, optr + off_in, data->strides_adj, iptr);

		/*
		// out(..,1,..) = in_adj(..,1,..)
		dims_sub[d] = 1;
		md_copy2(data->D, dims_sub,
		data->strides_in, optr, data->strides_adj, iptr, CFL_SIZE);

		// out(..,2:(end-1),..) = in(..,2:end,..) - in(..,1:(end-1),..)
		dims_sub[d] = nx - 1;
		off_adj = data->strides_adj[d]/CFL_SIZE;
		off_in = data->strides_in[d]/CFL_SIZE;
		md_zsub2(data->D, dims_sub, data->strides_in, optr+off_in,
		data->strides_adj, iptr+off_adj, data->strides_adj, iptr);

		// out(..,end,..) = -in(..,end,..);
		dims_sub[d] = 1;
		off_adj = (nx - 1) * data->strides_adj[d]/CFL_SIZE;
		off_in = nx * data->strides_in[d]/CFL_SIZE;
		// !!!This one operation is really really slow!!!
		md_zsmul2(data->D, dims_sub, data->strides_in, optr+off_in,
		data->strides_adj, iptr+off_adj, -1.);
		 */
	}
}
예제 #6
0
파일: finite_diff.c 프로젝트: mrirecon/bart
/**
 * Originally used md_circshift, but couldn't get it right, so I just
 * wrote it out for now (also avoids extra memory)
 */
static void zfinitediff_apply(const linop_data_t* _data,
		complex float* optr, const complex float* iptr)
{
	// if (docircshift)
	//     out(..,1:(end-1),..) = in(..,1:(end-1),..) - in(..,2:end,..)
	//     out(..,end,..) = in(..,end,..) - in(..,1,..)
	// else
	//     out = in(..,1:(end-1),..) - in(..,2:end,..)

	const auto data = CAST_DOWN(zfinitediff_data, _data);


	unsigned long d = data->dim_diff;
	long nx = data->dims_in[d];

	long dims_sub[data->D];
	md_copy_dims(data->D, dims_sub, data->dims_in);

	long off_in, off_adj;

	if (data->do_circdiff) {

		// out(..,1:(end-1),..) = in(..,1:(end-1),..) - in(..,2:end,..)
		dims_sub[d] = nx - 1;
		off_in = data->strides_in[d] / CFL_SIZE;
		//off_adj = data->strides_in[d]/CFL_SIZE;
		md_zsub2(data->D, dims_sub, data->strides_adj, optr,
				data->strides_in, iptr, data->strides_in, iptr + off_in);

		// out(..,end,..) = in(..,end,..) - in(..,1,..)
		dims_sub[d] = 1;
		off_in = (nx - 1) * data->strides_in[d] / CFL_SIZE;
		off_adj = (nx - 1) * data->strides_adj[d] / CFL_SIZE;
		md_zsub2(data->D, dims_sub, data->strides_adj, optr + off_adj,
				data->strides_in, iptr + off_in, data->strides_in, iptr);

	} else {
		// out(..,1:(end-1),..) = in(..,1:(end-1),..) - in(..,2:end,..)
		dims_sub[d] = nx - 1;
		off_in = data->strides_in[d] / CFL_SIZE;
		md_zsub2(data->D, dims_sub, data->strides_adj, optr,
				data->strides_in, iptr, data->strides_in, iptr + off_in);
	}

	/*
	   long i_shift, i_adj, x_orig, x_new;
	   unsigned int d = data->dim_diff;
	   for (unsigned int i = 0; i < md_calc_size(data->D, data->dims_in); i++) {
	   i_shift = i;
	   i_adj = i;

	   x_orig = (i/data->strs_in[d]) % data->dims_in[d];
	   x_new = x_orig + 1; // shift by 1

	   while (x_new >= data->dims_in[d]) x_new -= data->dims_in[d];

	   i_shift += (x_new - x_orig)*data->strs_in[d];

	   optr[i_adj] = iptr[i] - iptr[i_shift];
	 */
}