@@ -84,6 +84,9 @@ class Optimizer {
8484 " ❌ Error: Parameters dimensions cannot be 0 or Dynamic at "
8585 " execution time" );
8686 return StopReason::kSkipped ;
87+ } else if (dims < 0 ) {
88+ TINYOPT_LOG (" ❌ Error: Parameters dimensions is negative: {} " , dims);
89+ return StopReason::kSkipped ;
8790 }
8891
8992 // Resize the solver if needed TODO move?
@@ -450,6 +453,28 @@ class Optimizer {
450453 out.deltas2 .emplace_back (dx_norm2);
451454 out.successes .emplace_back (is_good_step);
452455
456+ // Update output struct
457+ if (is_good_step || iter == 0 ) { /* GOOD Step */
458+ // Note: we guess it's a good step in the first iteration
459+ if (iter > 0 ) solver_.GoodStep (options_.use_step_quality_approx ? rel_derr : 0 .0f );
460+ out.num_consec_failures = 0 ;
461+ out.final_cost = cost;
462+ out.final_rerr_dec = rel_derr;
463+ } else { /* BAD Step */
464+ solver_.BadStep ();
465+ out.num_failures ++;
466+ out.num_consec_failures ++;
467+ if (options_.max_consec_failures > 0 &&
468+ out.num_consec_failures >= options_.max_consec_failures ) {
469+ out.stop_reason = StopReason::kMaxConsecNoDecr ;
470+ return status;
471+ }
472+ if (options_.max_total_failures > 0 && out.num_failures >= options_.max_total_failures ) {
473+ out.stop_reason = StopReason::kMaxNoDecr ;
474+ return status;
475+ }
476+ }
477+
453478 // Log
454479 if (options_.log .enable ) {
455480 std::ostringstream oss;
@@ -478,7 +503,8 @@ class Optimizer {
478503
479504 // Print error/cost
480505 oss << TINYOPT_FORMAT_NS::format (" {}:{:.4e} n:{} d{}:{:+.2e} r{}:{:+.1e} " , options_.log .e ,
481- err, nerr, options_.log .e , derr, options_.log .e , rel_derr);
506+ err, nerr, options_.log .e , iter == 0 ? 0 .0f : derr,
507+ options_.log .e , rel_derr);
482508
483509 // Print step info
484510 oss << TINYOPT_FORMAT_NS::format (" |δx|:{:.2e} " , sqrt (dx_norm2));
@@ -505,28 +531,6 @@ class Optimizer {
505531 TINYOPT_LOG (" {}" , oss.str ());
506532 }
507533
508- // Update output struct
509- if (is_good_step) { /* GOOD Step */
510- // Note: we guess it's a good step in the first iteration
511- solver_.GoodStep (options_.use_step_quality_approx ? rel_derr : 0 .0f );
512- out.num_consec_failures = 0 ;
513- out.final_cost = cost;
514- out.final_rerr_dec = rel_derr;
515- } else { /* BAD Step */
516- solver_.BadStep ();
517- out.num_failures ++;
518- out.num_consec_failures ++;
519- if (options_.max_consec_failures > 0 &&
520- out.num_consec_failures >= options_.max_consec_failures ) {
521- out.stop_reason = StopReason::kMaxConsecNoDecr ;
522- return status;
523- }
524- if (options_.max_total_failures > 0 && out.num_failures >= options_.max_total_failures ) {
525- out.stop_reason = StopReason::kMaxNoDecr ;
526- return status;
527- }
528- }
529-
530534 // Detect if we need to stop
531535 if (solver_failed)
532536 out.stop_reason = StopReason::kSolverFailed ;
0 commit comments