// // C++ Implementation: itpp_ext // // Description: // // // Author: smidl , (C) 2008 // // Copyright: See COPYING file that comes with this distribution // // #include #include "itpp_ext.h" // from algebra/lapack.h extern "C" { /* QR factorization of a general matrix A */ void dgeqrf_(int *m, int *n, double *a, int *lda, double *tau, double *work, int *lwork, int *info); }; namespace itpp { Array to_Arr(const ivec &indices) { Array a(indices.size()); for (int i = 0; i < a.size(); i++) { a(i) = indices(i); } return a; } ivec linspace ( int from, int to ) { int n=to-from+1; int i; it_assert_debug ( n>0,"wrong linspace" ); ivec iv ( n ); for (i=0;i= 1.0) { x = -log((e - p) / a); if (exp_rand() >= (1.0 - a) * log(x)) break; } else { x = exp(log(p) / a); if (exp_rand() >= x) break; } } return scale * x; } /* --- a >= 1 : GD algorithm --- */ /* Step 1: Recalculations of s2, s, d if a has changed */ if (a != aa) { aa = a; s2 = a - 0.5; s = sqrt(s2); d = sqrt32 - s * 12.0; } /* Step 2: t = standard normal deviate, x = (s,1/2) -normal deviate. */ /* immediate acceptance (i) */ t = norm_rand(); x = s + 0.5 * t; ret_val = x * x; if (t >= 0.0) return scale * ret_val; /* Step 3: u = 0,1 - uniform sample. squeeze acceptance (s) */ u = unif_rand(); if ((d * u) <= (t * t * t)) return scale * ret_val; /* Step 4: recalculations of q0, b, si, c if necessary */ if (a != aaa) { aaa = a; r = 1.0 / a; q0 = ((((((q7 * r + q6) * r + q5) * r + q4) * r + q3) * r + q2) * r + q1) * r; /* Approximation depending on size of parameter a */ /* The constants in the expressions for b, si and c */ /* were established by numerical experiments */ if (a <= 3.686) { b = 0.463 + s + 0.178 * s2; si = 1.235; c = 0.195 / s - 0.079 + 0.16 * s; } else if (a <= 13.022) { b = 1.654 + 0.0076 * s2; si = 1.68 / s + 0.275; c = 0.062 / s + 0.024; } else { b = 1.77; si = 0.75; c = 0.1515 / s; } } /* Step 5: no quotient test if x not positive */ if (x > 0.0) { /* Step 6: calculation of v and quotient q */ v = t / (s + s); if (fabs(v) <= 0.25) q = q0 + 0.5 * t * t * ((((((a7 * v + a6) * v + a5) * v + a4) * v + a3) * v + a2) * v + a1) * v; else q = q0 - s * t + 0.25 * t * t + (s2 + s2) * log(1.0 + v); /* Step 7: quotient acceptance (q) */ if (log(1.0 - u) <= q) return scale * ret_val; } for(;;) { //VS repeat /* Step 8: e = standard exponential deviate * u = 0,1 -uniform deviate * t = (b,si)-double exponential (laplace) sample */ e = exp_rand(); u = unif_rand(); u = u + u - 1.0; if (u < 0.0) t = b - si * e; else t = b + si * e; /* Step 9: rejection if t < tau(1) = -0.71874483771719 */ if (t >= -0.71874483771719) { /* Step 10: calculation of v and quotient q */ v = t / (s + s); if (fabs(v) <= 0.25) q = q0 + 0.5 * t * t * ((((((a7 * v + a6) * v + a5) * v + a4) * v + a3) * v + a2) * v + a1) * v; else q = q0 - s * t + 0.25 * t * t + (s2 + s2) * log(1.0 + v); /* Step 11: hat acceptance (h) */ /* (if q not positive go to step 8) */ if (q > 0.0) { // TODO: w = expm1(q); w = exp(q)-1; /* ^^^^^ original code had approximation with rel.err < 2e-7 */ /* if t is rejected sample again at step 8 */ if ((c * fabs(u)) <= (w * exp(e - 0.5 * t * t))) break; } } } /* repeat .. until `t' is accepted */ x = s + 0.5 * t; return scale * x * x; } bool qr(const mat &A, mat &R) { int info; int m = A.rows(); int n = A.cols(); int lwork = n; int k = std::min(m, n); vec tau(k); vec work(lwork); R = A; // perform workspace query for optimum lwork value int lwork_tmp = -1; dgeqrf_(&m, &n, R._data(), &m, tau._data(), work._data(), &lwork_tmp, &info); if (info == 0) { lwork = static_cast(work(0)); work.set_size(lwork, false); } dgeqrf_(&m, &n, R._data(), &m, tau._data(), work._data(), &lwork, &info); // construct R for (int i=0; i