+std::vector<unsigned>
+matrix::echelon_form(unsigned algo, int n)
+{
+ // Here is the heuristics in case this routine has to decide:
+ if (algo == solve_algo::automatic) {
+ // Gather some statistical information about the augmented matrix:
+ bool numeric_flag = true;
+ for (auto & r : m) {
+ if (!r.info(info_flags::numeric)) {
+ numeric_flag = false;
+ break;
+ }
+ }
+ // Bareiss (fraction-free) elimination is generally a good guess:
+ algo = solve_algo::bareiss;
+ // For row<3, Bareiss elimination is equivalent to division free
+ // elimination but has more logistic overhead
+ if (row<3)
+ algo = solve_algo::divfree;
+ // This overrides any prior decisions.
+ if (numeric_flag)
+ algo = solve_algo::gauss;
+ }
+ // Eliminate the augmented matrix:
+ std::vector<unsigned> colid(col);
+ for (unsigned c = 0; c < col; c++) {
+ colid[c] = c;
+ }
+ switch(algo) {
+ case solve_algo::gauss:
+ gauss_elimination();
+ break;
+ case solve_algo::divfree:
+ division_free_elimination();
+ break;
+ case solve_algo::bareiss:
+ fraction_free_elimination();
+ break;
+ case solve_algo::markowitz:
+ colid = markowitz_elimination(n);
+ break;
+ default:
+ throw std::invalid_argument("matrix::echelon_form(): 'algo' is not one of the solve_algo enum");
+ }
+ return colid;
+}