/** * Create a linear operator (with strides) */ struct linop_s* linop_create2(unsigned int ON, const long odims[ON], const long ostrs[ON], unsigned int IN, const long idims[IN], const long istrs[IN], void* data, lop_fun_t forward, lop_fun_t adjoint, lop_fun_t normal, lop_p_fun_t norm_inv, del_fun_t del) { struct linop_s* lo = xmalloc(sizeof(struct linop_s)); struct shared_data_s* shared_data[4]; for (unsigned int i = 0; i < 4; i++) shared_data[i] = xmalloc(sizeof(struct shared_data_s)); for (unsigned int i = 0; i < 4; i++) { shared_data[i]->data = data; shared_data[i]->del = del; // circular double-linked list shared_data[i]->next = shared_data[(i + 1) % 4]; shared_data[i]->prev = shared_data[(i + 3) % 4]; } shared_data[0]->u.apply = forward; shared_data[1]->u.apply = adjoint; shared_data[2]->u.apply = normal; shared_data[3]->u.apply_p = norm_inv; assert((NULL != forward)); assert((NULL != adjoint)); lo->forward = operator_create2(ON, odims, ostrs, IN, idims, istrs, shared_data[0], shared_apply, shared_del); lo->adjoint = operator_create2(IN, idims, istrs, ON, odims, ostrs, shared_data[1], shared_apply, shared_del); if (NULL != normal) { lo->normal = operator_create2(IN, idims, istrs, IN, idims, istrs, shared_data[2], shared_apply, shared_del); } else { shared_unlink(shared_data[2]); free(shared_data[2]); lo->normal = NULL; } if (NULL != norm_inv) { lo->norm_inv = operator_p_create2(IN, idims, istrs, IN, idims, istrs, shared_data[3], shared_apply_p, shared_del); } else { shared_unlink(shared_data[3]); free(shared_data[3]); lo->norm_inv = NULL; } return lo; }
const struct operator_s* fft_create2(unsigned int D, const long dimensions[D], unsigned long flags, const long ostrides[D], complex float* dst, const long istrides[D], const complex float* src, bool backwards) { PTR_ALLOC(struct fft_plan_s, plan); SET_TYPEID(fft_plan_s, plan); plan->fftw = fft_fftwf_plan(D, dimensions, flags, ostrides, dst, istrides, src, backwards, false); #ifdef USE_CUDA plan->cuplan = NULL; #ifndef LAZY_CUDA if (cuda_ondevice(src)) plan->cuplan = fft_cuda_plan(D, dimensions, flags, ostrides, istrides, backwards); #else plan->D = D; plan->flags = flags; plan->backwards = backwards; PTR_ALLOC(long[D], dims); md_copy_dims(D, *dims, dimensions); plan->dims = *PTR_PASS(dims); PTR_ALLOC(long[D], istrs); md_copy_strides(D, *istrs, istrides); plan->istrs = *PTR_PASS(istrs); PTR_ALLOC(long[D], ostrs); md_copy_strides(D, *ostrs, ostrides); plan->ostrs = *PTR_PASS(ostrs); #endif #endif return operator_create2(D, dimensions, ostrides, D, dimensions, istrides, CAST_UP(PTR_PASS(plan)), fft_apply, fft_free_plan); }
const struct operator_s* fft_create2(unsigned int D, const long dimensions[D], unsigned long flags, const long ostrides[D], complex float* dst, const long istrides[D], const complex float* src, bool backwards) { PTR_ALLOC(struct fft_plan_s, plan); plan->fftw = fft_fftwf_plan(D, dimensions, flags, ostrides, dst, istrides, src, backwards); #ifdef USE_CUDA plan->cuplan = NULL; if (cuda_ondevice(src)) plan->cuplan = fft_cuda_plan(D, dimensions, flags, ostrides, istrides, backwards); #endif return operator_create2(D, dimensions, ostrides, D, dimensions, istrides, &PTR_PASS(plan)->base, fft_apply, fft_free_plan); }
const struct operator_s* fft_measure_create(unsigned int D, const long dimensions[D], unsigned long flags, bool inplace, bool backwards) { PTR_ALLOC(struct fft_plan_s, plan); SET_TYPEID(fft_plan_s, plan); complex float* src = md_alloc(D, dimensions, CFL_SIZE); complex float* dst = inplace ? src : md_alloc(D, dimensions, CFL_SIZE); long strides[D]; md_calc_strides(D, strides, dimensions, CFL_SIZE); plan->fftw = fft_fftwf_plan(D, dimensions, flags, strides, dst, strides, src, backwards, true); md_free(src); if (!inplace) md_free(dst); #ifdef USE_CUDA plan->cuplan = NULL; #ifndef LAZY_CUDA if (cuda_ondevice(src)) plan->cuplan = fft_cuda_plan(D, dimensions, flags, strides, strides, backwards); #else plan->D = D; plan->flags = flags; plan->backwards = backwards; PTR_ALLOC(long[D], dims); md_copy_dims(D, *dims, dimensions); plan->dims = *PTR_PASS(dims); PTR_ALLOC(long[D], istrs); md_copy_strides(D, *istrs, strides); plan->istrs = *PTR_PASS(istrs); PTR_ALLOC(long[D], ostrs); md_copy_strides(D, *ostrs, strides); plan->ostrs = *PTR_PASS(ostrs); #endif #endif return operator_create2(D, dimensions, strides, D, dimensions, strides, CAST_UP(PTR_PASS(plan)), fft_apply, fft_free_plan); }