docs: function qrDecomposition (A, inPlace) {
    const Q = A.clone().identity();
    const R = inPlace ? A : A.clone();
    const qe = Q.elements;
    const re = R.elements;
  
    const csr = [0, 0, 0];
    const DIM = Q.dimension;
    const m = DIM;
    const n = DIM;
    for (let j = 0; j < n; ++j) {
      for (let i = m - 1; i >= j + 1; --i) {
        const a = re[n * j + (i - 1)]; // R.get(i - 1, j);
        const b = re[n * j + i]; // R.get(i, j);
        if (a === 0 && b === 0) {
          continue;
        }
        rotg(a, b, csr);
        const c = csr[0];
        const s = csr[1];
        let tmp1 = 0;
        let tmp2 = 0;
  
        // R' = G * R
        for (let x = 0; x < n; ++x) {
          tmp1 = re[n * x + (i - 1)]; // R.get(i - 1, x);
          tmp2 = re[n * x + i]; // R.get(i, x);
          re[n * x + (i - 1)] = tmp1 * c + tmp2 * s; // R.set(i - 1, x, tmp1 * c + tmp2 * s);
          re[n * x + i] = -tmp1 * s + tmp2 * c; // R.set(i, x, -tmp1 * s + tmp2 * c);
        }
        re[n * j + (i - 1)] = csr[2]; // R.set(i - 1, j, csr[2]);
        re[n * j + i] = 0; // R.set(i, j, 0);
  
        // Q' = Q * G^T
        for (let x = 0; x < m; ++x) {
          tmp1 = qe[n * (i - 1) + x]; // Q.get(x, i - 1);
          tmp2 = qe[n * i + x]; // Q.get(x, i);
          qe[n * (i - 1) + x] = tmp1 * c + tmp2 * s; // Q.set(x, i - 1, tmp1 * c + tmp2 * s);
          qe[n * i + x] = -tmp1 * s + tmp2 * c; // Q.set(x, i, -tmp1 * s + tmp2 * c);
        }
      }
    }
    return { Q, R };
  }