void incomplete_qr(int m, int n, const int *Acolstart, const int *Arowindex, const double *Avalue, double Qdroptol, const int *Rcolstart, const int *Rrowindex, double *Rvalue, double *Rdiag) { // column storage for intermediate Q std::vector<StaticSparseVector> Q(n); // for each column of Q, how many more times it will be used in making R // (once this gets decremented to zero, we can free the column) std::vector<int> dependency_count(n,0); for(int i=0; i<n; ++i){ for(int a=Rcolstart[i]; a<Rcolstart[i+1]; ++a){ int j=Rrowindex[a]; if(j<i) ++dependency_count[j]; } } // construct R a column at a time for(int i=0; i<n; ++i){ DynamicSparseVector q; copy_column(Acolstart[i], Acolstart[i+1], Arowindex, Avalue, q); for(int a=Rcolstart[i]; a<Rcolstart[i+1]; ++a){ int j=Rrowindex[a]; if(j<i){ Rvalue[a]=dot_product(Q[j], q); add_to_vector(-Rvalue[a], Q[j], q); --dependency_count[j]; if(dependency_count[j]==0) Q[j].clear(); }else // j>i Rvalue[a]=0; // ideally structure of R is upper triangular, so this waste of space won't happen } Rdiag[i]=vector_norm(q); copy_large_entries(q, Qdroptol*Rdiag[i], Q[i]); normalize(Q[i]); } }
constexpr auto is_independent(TSystemSignature ss) { return mp::bool_v<(dependency_count(ss) == 0)>; }