/** * @brief Matrix vector product A*x * * Usage: * @code{.cpp} * Matrix<cxdb> A = rand<cxdb> (20,5); * Matrix<cxdb> x = rand<cxdb> (20,1); * double prod = gemv (A, x, 'C'); * @endcode * * @param A Matrix A * @param x Vector x * @param trans Transpose A? * * @return A*x */ template<class T> inline Matrix<T> gemv (const Matrix<T>& A, const Matrix<T>& x, char trans = 'N') { assert (isvec(x)); assert (isvec(A)||is2d(A)); int aw, ah, xh, m, n, one = 1; T alpha = (T)1., beta = (T)0.; // Column vector assert (size(x, 1) == 1); aw = (int) size (A, 1); ah = (int) size (A, 0); xh = (int) size (x, 0); m = ah; n = aw; if (trans == 'N') assert (aw == xh); else if (trans == 'T' || trans == 'C') assert (ah == xh); Matrix<T> y ((trans == 'N') ? m : n, 1); LapackTraits<T>::gemv (trans, m, n, alpha, A.Ptr(), ah, x.Ptr(), one, beta, &y[0], one); return y; }
Solution VDSpiral (SpiralParams& sp) { GradientParams gp; Matrix<double>& fov = sp.fov; Matrix<double>& rad = sp.rad; double k_max, fov_max, dr; Matrix<double> r, theta; long n = 0; assert (numel(rad) >= 2); assert (isvec(rad) == isvec(fov)); assert (numel(rad) == numel(fov)); k_max = 5.0 / sp.res; fov_max = m_max(fov); dr = sp.shots / (fov_max); n = size(fov,1)*100; r = linspace<double> (0.0, k_max, n); Matrix<double> x = k_max*rad; fov = interp1 (x, fov, r, INTERP::LINEAR); dr = sp.shots / (1500.0 * fov_max); n = ceil (k_max/dr); x = r; r = linspace<double> (0.0, k_max, n); fov = interp1 (x, fov, r, INTERP::AKIMA); theta = cumsum ((2 * PI * dr / sp.shots) * fov); gp.k = Matrix<double> (numel(r), 3); for (size_t i = 0; i < numel(r); i++) { gp.k(i,0) = r[i] * cos (theta[i]); gp.k(i,1) = r[i] * sin (theta[i]); } gp.mgr = sp.mgr; gp.msr = sp.msr; gp.dt = sp.dt; gp.gunits = sp.gunits; gp.lunits = sp.lunits; Solution s = ComputeGradient (gp); return s; }
/** * @brief FFT shift * * @param m TO be shifted * @return Shifted */ template <class T> inline Matrix<T> fftshift (const Matrix<T>& m, const bool& fw = true) { assert (isvec(m) || is2d(m) || is3d(m)); Matrix<size_t> tmp = resize(size(m),ndims(m),1); for (size_t i = 0; i<ndims(m); i++) if (tmp[i] == 0) tmp[i] = 1; container<size_t> d = tmp.Container(); // data side lengths container<size_t> c = floor(tmp/2).Container(); // center coords Matrix<T> res (vsize(m)); size_t oi[3]; size_t si[3]; for (oi[0] = 0; oi[0] < d[0]; oi[0]++) { si[0] = (oi[0] + c[0]) % d[0]; for (oi[1] = 0; oi[1] < d[1]; oi[1]++) { si[1] = (oi[1] + c[1]) % d[1]; for (oi[2] = 0; oi[2] < d[2]; oi[2]++) { si[2] = (oi[2] + c[2]) % d[2]; if (fw) res(si[0],si[1],si[2]) = m(oi[0],oi[1],oi[2]); else res(oi[0],oi[1],oi[2]) = m(si[0],si[1],si[2]); } } } return res; }
/** * @brief Matrix matrix multiplication * * Usage: * @code{.cpp} * Matrix<cxfl> m = rand<cxfl> (20,10); * Matrix<cxfl> x = rand<cxfl> (10, 6); * * m = gemm (m, b, 'N', 'C'); * @endcode * * @see BLAS routine xGEMM * * @param A Left factor * @param B Right factor * @param transa (N: A*... | T: A.'*... | C: A'*...) transpose left factor * @param transb (N: ...*B | T: ...*B.' | C: ...*B') transpose right factor * @return Product */ template<class T> inline Matrix<T> gemm (const Matrix<T>& A, const Matrix<T>& B, char transa = 'N', char transb = 'N') { assert (isvec(A)||is2d(A)); assert (isvec(B)||is2d(B)); int aw, ah, bw, bh, m, n, k; T alpha = (T)1., beta = (T)0.; aw = (int)size(A,1); ah = (int)size(A,0), bw = (int)size(B,1), bh = (int)size(B,0); // Check inner dimensions if ( transa == 'N' && transb == 'N' ) assert (aw == bh); else if ( transa == 'N' && (transb == 'T' || transb == 'C')) assert (aw == bw); else if ((transa == 'T' || transa == 'C') && transb == 'N' ) assert (ah == bh); else if ((transa == 'T' || transa == 'C') && (transb == 'T' || transb == 'C')) assert (ah == bw); if (transa == 'N') { m = ah; k = aw; } else if (transa == 'T' || transa == 'C') { m = aw; k = ah; } if (transb == 'N') n = bw; else if (transb == 'T' || transb == 'C') n = bh; Matrix<T> C(m,n); LapackTraits<T>::gemm (transa, transb, m, n, k, alpha, A.Ptr(), ah, B.Ptr(), bh, beta, &C[0], m); return C; }
/** * @brief Hann window * * @param size Side lengths * @param t Scaling factor * @return Window */ template <class T> inline Matrix< std::complex<T> > hannwindow (const Matrix<size_t>& size, const T& t) { size_t dim = size.Dim(0); assert (dim > 1 && dim < 4); Matrix<double> res; if (dim == 1) res = Matrix<double> (size[0], 1); else if (dim == 2) res = Matrix<double> (size[0], size[1]); else res = Matrix<double> (size[0], size[1], size[2]); float h, d; float m[3]; if (isvec(res)) { m[0] = 0.5 * size[0]; m[1] = 0.0; m[2] = 0.0; } else if (is2d(res)) { m[0] = 0.5 * size[0]; m[1] = 0.5 * size[1]; m[2] = 0.0; } else { m[0] = 0.5 * size[0]; m[1] = 0.5 * size[1]; m[2] = 0.5 * size[2]; } res = squeeze(res); for (size_t s = 0; s < res.Dim(2); s++) for (size_t r = 0; r < res.Dim(1); r++) for (size_t c = 0; c < res.Dim(0); c++) { d = pow( (float)pow(((float)c-m[0])/m[0],2) + pow(((float)r-m[1])/m[1],2) + pow(((float)s-m[2])/m[2],2) , (float)0.5); h = (d < 1) ? (0.5 + 0.5 * cos (PI * d)) : 0.0; res(c,r,s) = t * h; } return res; }