391 gmp_RR infinity_threshold,
394 std::chrono::steady_clock::time_point start =
395 std::chrono::steady_clock::now();
396 size_t solveLinearTime = 0, solveLinearCount = 0, evaluateTime = 0;
404 ERROR(
"outputs and inputs are in different rings");
413 ERROR(
"inputs: expected a dense mutable matrix");
418 ERROR(
"outputs: expected a dense mutable matrix");
421 if (out_extras ==
nullptr)
423 ERROR(
"output_extras: expected a dense mutable matrix");
429 auto& oe = out_extras->
getMat();
430 size_t n_sols = in.numColumns();
431 size_t n = in.numRows() - 1;
433 if (ou.numColumns() != n_sols or ou.numRows() != n + 2)
435 ERROR(
"output: wrong shape");
438 if (oe.numColumns() != n_sols or oe.numRows() != 2)
440 ERROR(
"output_extras: wrong shape");
444 const RT& C = in.ring();
445 typename RT::RealRingType R = C.real_ring();
447 typedef typename RT::ElementType ElementType;
448 typedef typename RT::Element Element;
449 typedef typename RT::RealRingType::Element RealElement;
450 typedef typename RT::RealRingType::ElementType RealElementType;
453 RealElement t_step(R), min_step2(R), epsilon2(R), infinity_threshold2(R);
454 R.set_from_BigReal(t_step, init_dt);
455 R.set_from_BigReal(min_step2, min_dt);
456 R.mult(min_step2, min_step2, min_step2);
457 R.set_from_BigReal(epsilon2, epsilon);
458 int tolerance_bits =
int(log2(fabs(R.coerceToDouble(epsilon2))));
459 R.mult(epsilon2, epsilon2, epsilon2);
460 R.set_from_BigReal(infinity_threshold2, infinity_threshold);
461 R.mult(infinity_threshold2, infinity_threshold2, infinity_threshold2);
462 int num_successes_before_increase = 3;
464 RealElement t0(R), dt(R), one_minus_t0(R), dx_norm2(R), x_norm2(R), abs2dc(R);
467 RealElement one(R), two(R), four(R), six(R), one_half(R), one_sixth(R);
468 RealElementType& dt_factor = one_half;
469 R.set_from_long(one, 1);
470 R.set_from_long(two, 2);
471 R.set_from_long(four, 4);
472 R.set_from_long(six, 6);
473 R.divide(one_half, one, two);
474 R.divide(one_sixth, one, six);
476 Element c_init(C), c_end(C), dc(C), one_half_dc(C);
497 DMat<RT> Jinv_times_random(C, n, 1);
499 ElementType& c0 = x0c0.
entry(n, 0);
500 ElementType& c1 = x1c1.
entry(n, 0);
501 ElementType& c = xc.
entry(n, 0);
502 RealElementType& tol2 = epsilon2;
503 bool linearSolve_success;
504 for (
size_t s = 0;
s < n_sols;
s++)
512 C.set(c_end, ou.entry(n,
s));
515 bool t0equals1 =
false;
521 C.subtract(dc, c_end, c_init);
524 R.divide(dt, dt, abs2dc);
526 int predictor_successes = 0;
529 while (status ==
PROCESSING and not t0equals1)
534 R.elem_text_out(o, t0,
true,
false,
false);
535 std::cout <<
"t0 = " << o.
str();
537 C.elem_text_out(o, c0,
true,
false,
false);
538 std::cout <<
", c0 = " << o.
str() << std::endl;
540 R.subtract(one_minus_t0, one, t0);
541 if (R.compare_elems(dt, one_minus_t0) > 0)
543 R.set(dt, one_minus_t0);
545 C.subtract(dc, c_end, c0);
550 C.subtract(dc, c_end, c0);
552 C.divide(dc, dc, one_minus_t0);
566 C.mult(one_half_dc, dc, one_half);
570 TIME(evaluateTime,
mHxt.evaluate(xc, Hxt))
576 TIME(solveLinearTime,
577 linearSolve_success =
582 if (linearSolve_success)
586 C.add(c, c, one_half_dc);
588 TIME(evaluateTime,
mHxt.evaluate(xc, Hxt))
594 TIME(solveLinearTime,
595 linearSolve_success =
601 if (linearSolve_success)
609 TIME(evaluateTime,
mHxt.evaluate(xc, Hxt));
615 TIME(solveLinearTime,
616 linearSolve_success =
622 if (linearSolve_success)
630 TIME(evaluateTime,
mHxt.evaluate(xc, Hxt));
636 TIME(solveLinearTime,
637 linearSolve_success =
643 if (linearSolve_success)
666 int n_corr_steps = 0;
667 if (linearSolve_success)
673 TIME(evaluateTime,
mHxH.evaluate(x1c1, HxH));
679 TIME(solveLinearTime,
680 linearSolve_success =
690 R.mult(x_norm2, x_norm2, tol2);
691 is_successful = R.compare_elems(dx_norm2, x_norm2) < 0;
693 while (not is_successful and n_corr_steps < max_corr_steps);
696 if (not linearSolve_success or not is_successful)
699 predictor_successes = 0;
700 R.mult(dt, dt, dt_factor);
702 C.abs_squared(abs2dc, dc);
703 if (R.compare_elems(abs2dc, min_step2) < 0)
709 predictor_successes = predictor_successes + 1;
710 MatOps::setFromSubmatrix(x1c1, 0, n, 0, 0, x0c0);
713 if (predictor_successes >= num_successes_before_increase)
715 predictor_successes = 0;
716 R.divide(dt, dt, dt_factor);
723 if (not linearSolve_success)
725 else if (checkPrecision and not t0equals1)
727 mHxH.evaluate(x0c0, HxH);
728 MatOps::setFromSubmatrix(HxH, 0, n - 1, 0, n - 1, LHSmat);
730 for (
int i = 0; i < n; i++) C.random(RHSmat.
entry(i, 0));
732 TIME(solveLinearTime,
734 LHSmat, RHSmat, Jinv_times_random););
737 norm2(Jinv_times_random,
743#define PRECISION_SAFETY_BITS 10
744 int more_bits =
int(log2(fabs(R.coerceToDouble(dx_norm2)))) / 2;
746 if (precision_needed<53) precision_needed = 53;
748 std::cout <<
"precision needed = " << precision_needed <<
" = "
750 << tolerance_bits <<
"(tolerance) + "
751 << more_bits <<
"(additional)\n"
752 <<
"current precision = " << R.get_precision() << std::endl;
753 if (R.get_precision() < precision_needed)
755 else if (R.get_precision() != 53 and
756 R.get_precision() > 2 * precision_needed)
759 std::cout <<
"status = " << status << std::endl;
765 if (R.compare_elems(infinity_threshold2, x_norm2) < 0)
769 if (R.is_zero(x_norm2))
773 R.divide(x_norm2, one, x_norm2);
774 if (R.compare_elems(infinity_threshold2, x_norm2) < 0)
782 for (
size_t i = 0; i <= n; i++) C.set(ou.entry(i,
s), x0c0.
entry(i, 0));
783 C.set(ou.entry(n + 1,
s), dc);
785 oe.ring().set_from_long(oe.entry(0,
s), status);
786 oe.ring().set_from_long(oe.entry(1,
s), count);
789 std::chrono::steady_clock::time_point
end = std::chrono::steady_clock::now();
792 std::cout <<
"-- track took "
793 << std::chrono::duration_cast<std::chrono::milliseconds>(
end -
797 std::cout <<
"-- # of solveLinear calls = " << solveLinearCount
799 std::cout <<
"-- time of solveLinear calls = " << solveLinearTime
800 <<
" ns." << std::endl;
801 std::cout <<
"-- time of evaluate calls = " << evaluateTime <<
" ns."