/** * Proximal function for f(z) = 0.5 || y - A z ||_2^2. * Solution is (A^H A + (1/mu) I)z = A^H y + (1/mu)(x_plus_u) * * @param prox_data should be of type prox_normaleq_data * @param mu proximal penalty * @param z output * @param x_plus_u input */ static void prox_normaleq_fun(const operator_data_t* prox_data, float mu, float* z, const float* x_plus_u) { struct prox_normaleq_data* pdata = CAST_DOWN(prox_normaleq_data, prox_data); if (0 == mu) { md_copy(1, MD_DIMS(pdata->size), z, x_plus_u, FL_SIZE); } else { float rho = 1. / mu; float* b = md_alloc_sameplace(1, MD_DIMS(pdata->size), FL_SIZE, x_plus_u); md_copy(1, MD_DIMS(pdata->size), b, pdata->adj, FL_SIZE); md_axpy(1, MD_DIMS(pdata->size), b, rho, x_plus_u); if (NULL == pdata->op->norm_inv) { struct iter_conjgrad_conf* cg_conf = pdata->cgconf; cg_conf->l2lambda = rho; iter_conjgrad(CAST_UP(cg_conf), pdata->op->normal, NULL, pdata->size, z, (float*)b, NULL); } else { linop_norm_inv_unchecked(pdata->op, rho, (complex float*)z, (const complex float*)b); } md_free(b); } }
/** * Wrapper for calling pseudo-inverse operation using italgos. */ extern void linop_norm_inv_iter(void* _o, float lambda, float* _dst, const float* _src) { struct linop_s* o = _o; complex float* dst = (complex float*)_dst; const complex float* src = (complex float*)_src; linop_norm_inv_unchecked(o, lambda, dst, src); }
void fd_proj_noninc(const struct linop_s* o, complex float* optr, const complex float* iptr) { struct fdiff_s* data = (struct fdiff_s*)linop_get_data(o); // FIXME: CAST? dump_cfl("impre", data->D, data->dims, iptr); complex float* tmp2 = md_alloc_sameplace(data->D, data->dims, CFL_SIZE, optr); linop_forward_unchecked(o, tmp2, iptr); long tmpdim = data->dims[0]; long dims2[data->D]; md_select_dims(data->D, ~0u, dims2, data->dims); dims2[0] *= 2; dump_cfl("dxpre", data->D, data->dims, tmp2); md_smin(data->D, dims2, (float*)optr, (float*)tmp2, 0.); // add back initial value dims2[0] = tmpdim; for (unsigned int i = 0; i < data->D; i++) { if (MD_IS_SET(data->flags, i)) { dims2[i] = 1; md_copy2(data->D, dims2, data->str, optr, data->str, tmp2, CFL_SIZE); break; } } dump_cfl("dxpost", data->D, data->dims, optr); linop_norm_inv_unchecked(o, 0., optr, optr); dump_cfl("impost", data->D, data->dims, optr); md_free(tmp2); }