Blame SOURCES/gsl-1.15-odeinitval2_upstream_rev4788.patch

5a51f0
diff -up wrk/ode-initval2/bsimp.c.wrk wrk/ode-initval2/bsimp.c
5a51f0
diff -U0 wrk/ode-initval2/ChangeLog.wrk wrk/ode-initval2/ChangeLog
5a51f0
--- wrk/ode-initval2/ChangeLog.wrk	2013-01-29 13:40:22.470035141 +0100
5a51f0
+++ wrk/ode-initval2/ChangeLog	2013-01-29 12:58:21.000000000 +0100
5a51f0
@@ -0,0 +1,52 @@
5a51f0
+2013-01-27  Tuomo Keskitalo  <tuomo.keskitalo@iki.fi>
5a51f0
+
5a51f0
+	* msbdf.c: Corrected bug which enabled order to be changed 
5a51f0
+	by two (first by stability enhancement, then by order evaluation
5a51f0
+	after a rejected step). Thanks for Frantisek Kluknavsky and
5a51f0
+	Andreas Schwab for bug reports!
5a51f0
+	
5a51f0
+	* msbdf.c: Added more state variables explicitly to be reset in 
5a51f0
+	msbdf_reset. 
5a51f0
+
5a51f0
+	*msbdf.c: Added abscorscaled to remove division of abscor for 
5a51f0
+	use in msbdf_eval_order and subsequent backwards multiplication.
5a51f0
+	
5a51f0
+	*test.c: test_extreme_problems: Increased ringmod case tolerances 
5a51f0
+	from 1e-7 to 1e-12 to increase precision. Because that
5a51f0
+	increases computational burden, I also decreased end time 
5a51f0
+	from 1e-3 to 1e-5. That decreased the acidity of the test 
5a51f0
+	significantly, but the test case is now more appropriate 
5a51f0
+	for normal "make check". Thanks for Frantisek Kluknavsky
5a51f0
+	for pointing out bad design of the test case.
5a51f0
+
5a51f0
+2012-09-10  Rhys Ulerich  <rhys.ulerich@gmail.com>
5a51f0
+
5a51f0
+	* test.c: Correct two out-of-order declarations.
5a51f0
+	Thanks to Brian Gladman for spotting the problem.
5a51f0
+
5a51f0
+2012-03-10  Tuomo Keskitalo  <tuomo.keskitalo@iki.fi>
5a51f0
+
5a51f0
+	* driver.c: Added function gsl_odeiv2_driver_reset_hstart to
5a51f0
+	allow resetting step size, possibly change its sign, too.
5a51f0
+	Check for non-zero hstart in initializations.
5a51f0
+
5a51f0
+	* test.c: Modified test_driver to carry out tests with all
5a51f0
+	steppers. Small printout changes.
5a51f0
+
5a51f0
+2012-01-21  Tuomo Keskitalo  <tuomo.keskitalo@iki.fi>
5a51f0
+
5a51f0
+	* rkf45.c: Bug correction: Set gives_exact_dydt_out to 1 in
5a51f0
+	rkf45_type
5a51f0
+
5a51f0
+2012-01-14  Tuomo Keskitalo  <tuomo.keskitalo@iki.fi>
5a51f0
+
5a51f0
+	* evolve.c: Modified initial derivative evaluation in evolve_apply
5a51f0
+	to reuse previously calculated values. This saves calls to the
5a51f0
+	user function. Thanks for Illes Farkas for pointing out redundant
5a51f0
+	function calls!
5a51f0
+
5a51f0
+2011-06-28  Brian Gough  <bjg@network-theory.co.uk>
5a51f0
+
5a51f0
+	* rk4imp.c (rk4imp_apply): use M_SQRT3 instead of sqrt(3) in array
5a51f0
+	initialiser.
5a51f0
+
5a51f0
diff -up wrk/ode-initval2/control.c.wrk wrk/ode-initval2/control.c
5a51f0
diff -up wrk/ode-initval2/control_utils.c.wrk wrk/ode-initval2/control_utils.c
5a51f0
diff -up wrk/ode-initval2/cscal.c.wrk wrk/ode-initval2/cscal.c
5a51f0
diff -up wrk/ode-initval2/cstd.c.wrk wrk/ode-initval2/cstd.c
5a51f0
diff -up wrk/ode-initval2/driver.c.wrk wrk/ode-initval2/driver.c
5a51f0
--- wrk/ode-initval2/driver.c.wrk	2013-01-29 13:40:22.508035371 +0100
5a51f0
+++ wrk/ode-initval2/driver.c	2013-01-29 13:07:29.000000000 +0100
5a51f0
@@ -81,7 +81,7 @@ driver_alloc (const gsl_odeiv2_system *
5a51f0
       GSL_ERROR_NULL ("failed to allocate evolve object", GSL_ENOMEM);
5a51f0
     }
5a51f0
 
5a51f0
-  if (hstart >= 0.0 || hstart < 0.0)
5a51f0
+  if (hstart > 0.0 || hstart < 0.0)
5a51f0
     {
5a51f0
       state->h = hstart;
5a51f0
     }
5a51f0
@@ -459,6 +459,29 @@ gsl_odeiv2_driver_reset (gsl_odeiv2_driv
5a51f0
   return GSL_SUCCESS;
5a51f0
 }
5a51f0
 
5a51f0
+int
5a51f0
+gsl_odeiv2_driver_reset_hstart (gsl_odeiv2_driver * d, const double hstart)
5a51f0
+{
5a51f0
+  /* Resets current driver and sets initial step size to hstart */
5a51f0
+
5a51f0
+  gsl_odeiv2_driver_reset (d);
5a51f0
+
5a51f0
+  if ((d->hmin > fabs (hstart)) || (fabs (hstart) > d->hmax))
5a51f0
+    {
5a51f0
+      GSL_ERROR_NULL ("hmin <= fabs(h) <= hmax required", GSL_EINVAL);
5a51f0
+    }
5a51f0
+
5a51f0
+  if (hstart > 0.0 || hstart < 0.0)
5a51f0
+    {
5a51f0
+      d->h = hstart;
5a51f0
+    }
5a51f0
+  else
5a51f0
+    {
5a51f0
+      GSL_ERROR_NULL ("invalid hstart", GSL_EINVAL);
5a51f0
+    }
5a51f0
+
5a51f0
+  return GSL_SUCCESS;
5a51f0
+}
5a51f0
 
5a51f0
 void
5a51f0
 gsl_odeiv2_driver_free (gsl_odeiv2_driver * state)
5a51f0
diff -up wrk/ode-initval2/evolve.c.wrk wrk/ode-initval2/evolve.c
5a51f0
--- wrk/ode-initval2/evolve.c.wrk	2013-01-29 13:40:22.482035214 +0100
5a51f0
+++ wrk/ode-initval2/evolve.c	2013-01-29 13:07:32.000000000 +0100
5a51f0
@@ -138,16 +138,24 @@ gsl_odeiv2_evolve_apply (gsl_odeiv2_evol
5a51f0
 
5a51f0
   DBL_MEMCPY (e->y0, y, e->dimension);
5a51f0
 
5a51f0
-  /* Calculate initial dydt once if the method can benefit. */
5a51f0
-
5a51f0
+  /* Calculate initial dydt once or reuse previous value if the method
5a51f0
+     can benefit. */
5a51f0
+  
5a51f0
   if (step->type->can_use_dydt_in)
5a51f0
     {
5a51f0
-      int status = GSL_ODEIV_FN_EVAL (dydt, t0, y, e->dydt_in);
5a51f0
+      if (e->count == 0)
5a51f0
+	{
5a51f0
+	  int status = GSL_ODEIV_FN_EVAL (dydt, t0, y, e->dydt_in);
5a51f0
 
5a51f0
-      if (status)
5a51f0
-        {
5a51f0
-          return status;
5a51f0
-        }
5a51f0
+	  if (status)
5a51f0
+	    {
5a51f0
+	      return status;
5a51f0
+	    }
5a51f0
+	}
5a51f0
+      else
5a51f0
+	{
5a51f0
+	  DBL_MEMCPY (e->dydt_in, e->dydt_out, e->dimension);
5a51f0
+	}
5a51f0
     }
5a51f0
 
5a51f0
 try_step:
5a51f0
diff -up wrk/ode-initval2/gsl_odeiv2.h.wrk wrk/ode-initval2/gsl_odeiv2.h
5a51f0
--- wrk/ode-initval2/gsl_odeiv2.h.wrk	2013-01-29 13:40:22.468035129 +0100
5a51f0
+++ wrk/ode-initval2/gsl_odeiv2.h	2013-01-29 13:07:52.000000000 +0100
5a51f0
@@ -326,6 +326,7 @@ int gsl_odeiv2_driver_apply_fixed_step (
5a51f0
                                         const unsigned long int n,
5a51f0
                                         double y[]);
5a51f0
 int gsl_odeiv2_driver_reset (gsl_odeiv2_driver * d);
5a51f0
+int gsl_odeiv2_driver_reset_hstart (gsl_odeiv2_driver * d, const double hstart);
5a51f0
 void gsl_odeiv2_driver_free (gsl_odeiv2_driver * state);
5a51f0
 
5a51f0
 __END_DECLS
5a51f0
diff -up wrk/ode-initval2/Makefile.am.wrk wrk/ode-initval2/Makefile.am
5a51f0
diff -up wrk/ode-initval2/Makefile.in.wrk wrk/ode-initval2/Makefile.in
5a51f0
diff -up wrk/ode-initval2/modnewton1.c.wrk wrk/ode-initval2/modnewton1.c
5a51f0
diff -up wrk/ode-initval2/msadams.c.wrk wrk/ode-initval2/msadams.c
5a51f0
diff -up wrk/ode-initval2/msbdf.c.wrk wrk/ode-initval2/msbdf.c
5a51f0
--- wrk/ode-initval2/msbdf.c.wrk	2013-01-29 13:40:22.473035159 +0100
5a51f0
+++ wrk/ode-initval2/msbdf.c	2013-01-28 10:42:35.000000000 +0100
5a51f0
@@ -82,6 +82,7 @@ typedef struct
5a51f0
   size_t *ordprevbackup;        /* backup of ordprev */
5a51f0
   double *errlev;               /* desired error level of y */
5a51f0
   gsl_vector *abscor;           /* absolute y values for correction */
5a51f0
+  gsl_vector *abscorscaled;     /* scaled abscor for order evaluation */
5a51f0
   gsl_vector *relcor;           /* relative y values for correction */
5a51f0
   gsl_vector *svec;             /* saved abscor & work area */
5a51f0
   gsl_vector *tempvec;          /* work area */
5a51f0
@@ -91,7 +92,6 @@ typedef struct
5a51f0
   gsl_matrix *M;                /* Newton iteration matrix */
5a51f0
   gsl_permutation *p;           /* permutation for LU decomposition of M */
5a51f0
   gsl_vector *rhs;              /* right hand side equations (-G) */
5a51f0
-
5a51f0
   long int ni;                  /* stepper call counter */
5a51f0
   size_t ord;                   /* current order of method */
5a51f0
   double tprev;                 /* t point of previous call */
5a51f0
@@ -446,6 +446,33 @@ msbdf_alloc (size_t dim)
5a51f0
       GSL_ERROR_NULL ("failed to allocate space for rhs", GSL_ENOMEM);
5a51f0
     }
5a51f0
 
5a51f0
+  state->abscorscaled = gsl_vector_alloc (dim);
5a51f0
+
5a51f0
+  if (state->abscorscaled == 0)
5a51f0
+    {
5a51f0
+      gsl_vector_free (state->rhs); 
5a51f0
+      gsl_permutation_free (state->p);
5a51f0
+      gsl_matrix_free (state->M);
5a51f0
+      free (state->dfdt);
5a51f0
+      gsl_matrix_free (state->dfdy);
5a51f0
+      gsl_vector_free (state->tempvec);
5a51f0
+      gsl_vector_free (state->svec);
5a51f0
+      gsl_vector_free (state->relcor);
5a51f0
+      gsl_vector_free (state->abscor);
5a51f0
+      free (state->errlev);
5a51f0
+      free (state->ordprevbackup);
5a51f0
+      free (state->ordprev);
5a51f0
+      free (state->hprevbackup);
5a51f0
+      free (state->hprev);
5a51f0
+      free (state->l);
5a51f0
+      free (state->ytmp2);
5a51f0
+      free (state->ytmp);
5a51f0
+      free (state->zbackup);
5a51f0
+      free (state->z);
5a51f0
+      free (state);
5a51f0
+      GSL_ERROR_NULL ("failed to allocate space for abscorscaled", GSL_ENOMEM);
5a51f0
+    }
5a51f0
+
5a51f0
   msbdf_reset ((void *) state, dim);
5a51f0
 
5a51f0
   state->driver = NULL;
5a51f0
@@ -926,14 +953,14 @@ msbdf_corrector (void *vstate, const gsl
5a51f0
 }
5a51f0
 
5a51f0
 static int
5a51f0
-msbdf_eval_order (gsl_vector * abscor, gsl_vector * tempvec,
5a51f0
+msbdf_eval_order (gsl_vector * abscorscaled, gsl_vector * tempvec,
5a51f0
                   gsl_vector * svec, const double errcoeff,
5a51f0
                   const size_t dim, const double errlev[],
5a51f0
                   const double ordm1coeff, const double ordp1coeff,
5a51f0
                   const double ordp1coeffprev, const double ordp2coeff,
5a51f0
                   const double hprev[],
5a51f0
                   const double h, const double z[],
5a51f0
-                  size_t * ord, size_t * ordwait)
5a51f0
+                  size_t * ord)
5a51f0
 {
5a51f0
   /* Evaluates and executes change in method order (current, current-1
5a51f0
      or current+1). Order which maximizes the step length is selected.
5a51f0
@@ -953,7 +980,7 @@ msbdf_eval_order (gsl_vector * abscor, g
5a51f0
 
5a51f0
   /* Relative step length estimate for current order */
5a51f0
 
5a51f0
-  ordest = 1.0 / (pow (bias * gsl_blas_dnrm2 (abscor) / sqrt (dim)
5a51f0
+  ordest = 1.0 / (pow (bias * gsl_blas_dnrm2 (abscorscaled) / sqrt (dim)
5a51f0
                        * errcoeff, 1.0 / (*ord + 1)) + safety);
5a51f0
 
5a51f0
   /* Relative step length estimate for order ord - 1 */
5a51f0
@@ -983,7 +1010,7 @@ msbdf_eval_order (gsl_vector * abscor, g
5a51f0
       for (i = 0; i < dim; i++)
5a51f0
         {
5a51f0
           gsl_vector_set (svec, i, gsl_vector_get (svec, i) * c +
5a51f0
-                          gsl_vector_get (abscor, i));
5a51f0
+                          gsl_vector_get (abscorscaled, i));
5a51f0
         }
5a51f0
 
5a51f0
       ordp1est = 1.0 / (pow (bias2 * gsl_blas_dnrm2 (svec) / sqrt (dim)
5a51f0
@@ -1020,8 +1047,6 @@ msbdf_eval_order (gsl_vector * abscor, g
5a51f0
 #endif
5a51f0
     }
5a51f0
 
5a51f0
-  *ordwait = *ord + 2;
5a51f0
-
5a51f0
   return GSL_SUCCESS;
5a51f0
 }
5a51f0
 
5a51f0
@@ -1096,6 +1121,7 @@ msbdf_apply (void *vstate, size_t dim, d
5a51f0
   size_t *const ordprevbackup = state->ordprevbackup;
5a51f0
   double *const errlev = state->errlev;
5a51f0
   gsl_vector *const abscor = state->abscor;
5a51f0
+  gsl_vector *const abscorscaled = state->abscorscaled;
5a51f0
   gsl_vector *const relcor = state->relcor;
5a51f0
   gsl_vector *const svec = state->svec;
5a51f0
   gsl_vector *const tempvec = state->tempvec;
5a51f0
@@ -1591,13 +1617,16 @@ msbdf_apply (void *vstate, size_t dim, d
5a51f0
       }
5a51f0
   }
5a51f0
 
5a51f0
-  /* Scale abscor with errlev for later use in norm calculations */
5a51f0
+  /* Scale abscor with errlev for later use in norm calculations
5a51f0
+     in order evaluation in msbdf_eval_order
5a51f0
+   */
5a51f0
   {
5a51f0
     size_t i;
5a51f0
 
5a51f0
     for (i = 0; i < dim; i++)
5a51f0
       {
5a51f0
-        gsl_vector_set (abscor, i, gsl_vector_get (abscor, i) / errlev[i]);
5a51f0
+        gsl_vector_set (abscorscaled, i, 
5a51f0
+                        gsl_vector_get (abscor, i) / errlev[i]);
5a51f0
       }
5a51f0
   }
5a51f0
 
5a51f0
@@ -1613,27 +1642,28 @@ msbdf_apply (void *vstate, size_t dim, d
5a51f0
 
5a51f0
       for (i = 0; i < dim; i++)
5a51f0
         {
5a51f0
-          gsl_vector_set (svec, i, gsl_vector_get (abscor, i));
5a51f0
+          gsl_vector_set (svec, i, gsl_vector_get (abscorscaled, i));
5a51f0
         }
5a51f0
     }
5a51f0
 
5a51f0
-  /* Consider and execute order change for next step */
5a51f0
+  /* Consider and execute order change for next step if order is unchanged. */
5a51f0
 
5a51f0
-  if (state->ordwait == 0)
5a51f0
-    {
5a51f0
-      msbdf_eval_order (abscor, tempvec, svec, errcoeff, dim, errlev,
5a51f0
-                        ordm1coeff, ordp1coeff,
5a51f0
-                        state->ordp1coeffprev, ordp2coeff,
5a51f0
-                        hprev, h, z, &(state->ord), &(state->ordwait));
5a51f0
-    }
5a51f0
+  if (state->ordwait == 0) 
5a51f0
+  { 
5a51f0
+    if (ord - ordprev[0] == 0)
5a51f0
+      {
5a51f0
+        msbdf_eval_order (abscorscaled, tempvec, svec, errcoeff, dim, errlev,
5a51f0
+                          ordm1coeff, ordp1coeff,
5a51f0
+                          state->ordp1coeffprev, ordp2coeff,
5a51f0
+                          hprev, h, z, &(state->ord));
5a51f0
 
5a51f0
-  /* Undo scaling of abscor for possible order increase on next step */
5a51f0
-  {
5a51f0
-    size_t i;
5a51f0
-    
5a51f0
-    for (i = 0; i < dim; i++)
5a51f0
+        state->ordwait = state->ord + 2;
5a51f0
+      }
5a51f0
+    else
5a51f0
       {
5a51f0
-        gsl_vector_set (abscor, i, gsl_vector_get (abscor, i) * errlev[i]);
5a51f0
+        /* Postpone order evaluation if order has been modified elsewhere */
5a51f0
+    
5a51f0
+        state->ordwait = 2;
5a51f0
       }
5a51f0
   }
5a51f0
   
5a51f0
@@ -1701,10 +1731,13 @@ msbdf_reset (void *vstate, size_t dim)
5a51f0
   state->ordwaitbackup = 2;
5a51f0
   state->failord = 0;
5a51f0
   state->failt = GSL_NAN;
5a51f0
+  state->tprev = GSL_NAN;  
5a51f0
   state->gammaprev = 1.0;
5a51f0
+  state->gammaprevbackup = 1.0;
5a51f0
   state->nJ = 0;
5a51f0
   state->nM = 0;
5a51f0
   state->failcount = 0;
5a51f0
+  state->ordp1coeffprev = 0.0;
5a51f0
 
5a51f0
   DBL_ZERO_MEMSET (state->hprev, MSBDF_MAX_ORD);
5a51f0
   DBL_ZERO_MEMSET (state->hprevbackup, MSBDF_MAX_ORD);
5a51f0
diff -up wrk/ode-initval2/odeiv_util.h.wrk wrk/ode-initval2/odeiv_util.h
5a51f0
diff -up wrk/ode-initval2/rk1imp.c.wrk wrk/ode-initval2/rk1imp.c
5a51f0
diff -up wrk/ode-initval2/rk2.c.wrk wrk/ode-initval2/rk2.c
5a51f0
diff -up wrk/ode-initval2/rk2imp.c.wrk wrk/ode-initval2/rk2imp.c
5a51f0
diff -up wrk/ode-initval2/rk4.c.wrk wrk/ode-initval2/rk4.c
5a51f0
diff -up wrk/ode-initval2/rk4imp.c.wrk wrk/ode-initval2/rk4imp.c
5a51f0
--- wrk/ode-initval2/rk4imp.c.wrk	2013-01-29 13:40:22.479035196 +0100
5a51f0
+++ wrk/ode-initval2/rk4imp.c	2013-01-29 13:08:32.000000000 +0100
5a51f0
@@ -249,7 +249,7 @@ rk4imp_apply (void *vstate, size_t dim,
5a51f0
   gsl_matrix *A = state->A;
5a51f0
 
5a51f0
   const double b[] = { 0.5, 0.5 };
5a51f0
-  const double c[] = { (3 - sqrt (3)) / 6, (3 + sqrt (3)) / 6 };
5a51f0
+  const double c[] = { (3.0 - M_SQRT3) / 6.0, (3.0 + M_SQRT3) / 6.0 };
5a51f0
 
5a51f0
   gsl_matrix_set (A, 0, 0, 1.0 / 4);
5a51f0
   gsl_matrix_set (A, 0, 1, (3 - 2 * sqrt (3)) / 12);
5a51f0
diff -up wrk/ode-initval2/rk8pd.c.wrk wrk/ode-initval2/rk8pd.c
5a51f0
diff -up wrk/ode-initval2/rkck.c.wrk wrk/ode-initval2/rkck.c
5a51f0
diff -up wrk/ode-initval2/rkf45.c.wrk wrk/ode-initval2/rkf45.c
5a51f0
--- wrk/ode-initval2/rkf45.c.wrk	2013-01-29 13:40:22.464035105 +0100
5a51f0
+++ wrk/ode-initval2/rkf45.c	2013-01-29 13:08:45.000000000 +0100
5a51f0
@@ -369,7 +369,7 @@ rkf45_free (void *vstate)
5a51f0
 
5a51f0
 static const gsl_odeiv2_step_type rkf45_type = { "rkf45",       /* name */
5a51f0
   1,                            /* can use dydt_in */
5a51f0
-  0,                            /* gives exact dydt_out */
5a51f0
+  1,                            /* gives exact dydt_out */
5a51f0
   &rkf45_alloc,
5a51f0
   &rkf45_apply,
5a51f0
   &stepper_set_driver_null,
5a51f0
diff -up wrk/ode-initval2/rksubs.c.wrk wrk/ode-initval2/rksubs.c
5a51f0
diff -up wrk/ode-initval2/step.c.wrk wrk/ode-initval2/step.c
5a51f0
diff -up wrk/ode-initval2/step_utils.c.wrk wrk/ode-initval2/step_utils.c
5a51f0
diff -up wrk/ode-initval2/test.c.wrk wrk/ode-initval2/test.c
5a51f0
--- wrk/ode-initval2/test.c.wrk	2013-01-29 13:40:22.487035244 +0100
5a51f0
+++ wrk/ode-initval2/test.c	2013-01-28 10:42:50.000000000 +0100
5a51f0
@@ -163,7 +163,7 @@ rhs_xsin (double t, const double y[], do
5a51f0
   static int n = 0, m = 0;
5a51f0
   extern int nfe;
5a51f0
   nfe += 1;
5a51f0
-  
5a51f0
+
5a51f0
   if (rhs_xsin_reset)
5a51f0
     {
5a51f0
       rhs_xsin_reset = 0;
5a51f0
@@ -1073,6 +1073,7 @@ test_odeiv_stepper (const gsl_odeiv2_ste
5a51f0
 
5a51f0
   {
5a51f0
     int s = gsl_odeiv2_step_apply (d->s, t, h, y, yerr, 0, 0, sys);
5a51f0
+
5a51f0
     if (s != GSL_SUCCESS)
5a51f0
       {
5a51f0
         gsl_test (s, "test_odeiv_stepper: %s step_apply returned %d", desc,
5a51f0
@@ -1191,13 +1192,13 @@ test_evolve_system (const gsl_odeiv2_ste
5a51f0
       if (s != GSL_SUCCESS)
5a51f0
         {
5a51f0
           /* check that t and y are unchanged */
5a51f0
-          gsl_test_abs (t, t_orig, 0.0, "%s, t must be restored on failure",
5a51f0
+          gsl_test_abs (t, t_orig, 0.0, "%s t must be restored on failure",
5a51f0
                         gsl_odeiv2_step_name (d->s));
5a51f0
 
5a51f0
           for (i = 0; i < sys->dimension; i++)
5a51f0
             {
5a51f0
               gsl_test_abs (y[i], y_orig[i], 0.0,
5a51f0
-                            "%s, y must be restored on failure",
5a51f0
+                            "%s y must be restored on failure",
5a51f0
                             gsl_odeiv2_step_name (d->s), desc, i);
5a51f0
             }
5a51f0
 
5a51f0
@@ -1259,11 +1260,11 @@ sys_driver (const gsl_odeiv2_step_type *
5a51f0
   gsl_odeiv2_driver *d =
5a51f0
     gsl_odeiv2_driver_alloc_standard_new (sys, T, h, epsabs, epsrel,
5a51f0
                                           1.0, 0.0);
5a51f0
-  
5a51f0
+
5a51f0
   extern int nfe, nje;
5a51f0
   nfe = 0;
5a51f0
   nje = 0;
5a51f0
-  
5a51f0
+
5a51f0
   while (t < t1)
5a51f0
     {
5a51f0
       s = gsl_odeiv2_evolve_apply (d->e, d->c, d->s, sys, &t, t1, &h, y);
5a51f0
@@ -1570,7 +1571,8 @@ test_user_break (const gsl_odeiv2_step_t
5a51f0
 
5a51f0
   int s = gsl_odeiv2_driver_apply (d, &t, t1, y);
5a51f0
 
5a51f0
-  gsl_test ((s - GSL_EBADFUNC), "test_user_break returned %d", s);
5a51f0
+  gsl_test ((s - GSL_EBADFUNC), "%s test_user_break returned %d",
5a51f0
+            gsl_odeiv2_step_name (d->s), s);
5a51f0
 
5a51f0
   gsl_odeiv2_driver_free (d);
5a51f0
 }
5a51f0
@@ -1938,17 +1940,15 @@ test_extreme_problems (void)
5a51f0
   const size_t sd[] = { 4, 3, NRINGMOD };
5a51f0
 
5a51f0
   /* Integration interval for problems */
5a51f0
+  
5a51f0
   const double start[CONST_EXTREME_NPROB] = { 0.0 };
5a51f0
-  const double end[CONST_EXTREME_NPROB] = { 1e11, 1e11, 1e-3 };
5a51f0
+  const double end[CONST_EXTREME_NPROB] = { 1e11, 1e11, 1e-5 };
5a51f0
 
5a51f0
   const double epsabs[CONST_EXTREME_NPROB] =
5a51f0
-    { 1e1 * GSL_DBL_MIN, 1e1 * GSL_DBL_MIN, 1e-7 };
5a51f0
-  const double epsrel[CONST_EXTREME_NPROB] = { 1e-12, 1e-12, 1e-7 };
5a51f0
+    { 1e1 * GSL_DBL_MIN, 1e1 * GSL_DBL_MIN, 1e-12 };
5a51f0
+  const double epsrel[CONST_EXTREME_NPROB] = { 1e-12, 1e-12, 1e-12 };
5a51f0
   const double initstepsize[CONST_EXTREME_NPROB] = { 1e-5, 1e-5, 1e-10 };
5a51f0
 
5a51f0
-  /* Problem specific tolerance modification coefficients */
5a51f0
-  const double pec[CONST_EXTREME_NPROB] = { 1.0, 1.0, 1e1 };
5a51f0
-
5a51f0
   /* Steppers */
5a51f0
 
5a51f0
   steppers[0] = gsl_odeiv2_step_bsimp;
5a51f0
@@ -2024,7 +2024,7 @@ test_extreme_problems (void)
5a51f0
             const double val1 = y[k];
5a51f0
             const double val2 = y[sd[p] * i + k];
5a51f0
             gsl_test_rel (val1, val2,
5a51f0
-                          (pec[p] * GSL_MAX (err_target[0], err_target[i])),
5a51f0
+                          (GSL_MAX (err_target[0], err_target[i])),
5a51f0
                           "%s/%s %s [%d]",
5a51f0
                           steppers[0]->name, steppers[i]->name,
5a51f0
                           probname[p], k);
5a51f0
@@ -2033,57 +2033,81 @@ test_extreme_problems (void)
5a51f0
 }
5a51f0
 
5a51f0
 void
5a51f0
-test_driver (void)
5a51f0
+test_driver (const gsl_odeiv2_step_type * T)
5a51f0
 {
5a51f0
   /* Tests for gsl_odeiv2_driver object */
5a51f0
+
5a51f0
   int s;
5a51f0
   const double tol = 1e-8;
5a51f0
   const double hmax = 1e-2;
5a51f0
 
5a51f0
   double y[] = { 1.0, 0.0 };
5a51f0
   double t = 0.0;
5a51f0
+  const double tinit = 0.0;
5a51f0
   const double t1 = 8.25;
5a51f0
   const double t2 = 100;
5a51f0
   const double t3 = -2.5;
5a51f0
   const size_t minsteps = ceil (t1 / hmax);
5a51f0
   const size_t maxsteps = 20;
5a51f0
   const double hmin = 1e-10;
5a51f0
-  const size_t nfsteps = 100;
5a51f0
-  
5a51f0
-  gsl_odeiv2_driver *d =
5a51f0
-    gsl_odeiv2_driver_alloc_y_new (&rhs_func_sin, gsl_odeiv2_step_rkf45,
5a51f0
-                                   1e-3, tol, tol);
5a51f0
+
5a51f0
+  const unsigned long int nfsteps = 100000;
5a51f0
+  const double hfixed = 0.000025;
5a51f0
+
5a51f0
+  gsl_odeiv2_driver *d = gsl_odeiv2_driver_alloc_y_new (&rhs_func_sin, T,
5a51f0
+                                                        1e-3, tol, tol);
5a51f0
   gsl_odeiv2_driver_set_hmax (d, hmax);
5a51f0
 
5a51f0
   s = gsl_odeiv2_driver_apply (d, &t, t1, y);
5a51f0
 
5a51f0
   if (s != GSL_SUCCESS)
5a51f0
     {
5a51f0
-      gsl_test (s, "test_driver apply returned %d", s);
5a51f0
+      gsl_test (s, "%s test_driver apply returned %d",
5a51f0
+                gsl_odeiv2_step_name (d->s), s);
5a51f0
     }
5a51f0
 
5a51f0
   /* Test that result is correct */
5a51f0
 
5a51f0
-  gsl_test_rel (y[0], cos (t1), d->n * tol, "test_driver y0 ");
5a51f0
-  gsl_test_rel (y[1], sin (t1), d->n * tol, "test_driver y1 ");
5a51f0
+  gsl_test_rel (y[0], cos (t1), d->n * tol, "%s test_driver y0",
5a51f0
+                gsl_odeiv2_step_name (d->s));
5a51f0
+  gsl_test_rel (y[1], sin (t1), d->n * tol, "%s test_driver y1",
5a51f0
+                gsl_odeiv2_step_name (d->s));
5a51f0
 
5a51f0
   /* Test that maximum step length is obeyed */
5a51f0
 
5a51f0
   if (d->n < minsteps)
5a51f0
     {
5a51f0
-      gsl_test (1, "test_driver steps %d < minsteps %d \n", d->n, minsteps);
5a51f0
+      gsl_test (1, "%s test_driver steps %d < minsteps %d \n",
5a51f0
+                gsl_odeiv2_step_name (d->s), d->n, minsteps);
5a51f0
     }
5a51f0
   else
5a51f0
     {
5a51f0
-      gsl_test (0, "test_driver max step length test");
5a51f0
+      gsl_test (0, "%s test_driver max step length test",
5a51f0
+                gsl_odeiv2_step_name (d->s));
5a51f0
     }
5a51f0
 
5a51f0
+  /* Test changing integration direction from forward to backward */
5a51f0
+
5a51f0
+  gsl_odeiv2_driver_reset_hstart (d, -1e-3);
5a51f0
+
5a51f0
+  s = gsl_odeiv2_driver_apply (d, &t, tinit, y);
5a51f0
+
5a51f0
+  if (s != GSL_SUCCESS)
5a51f0
+    {
5a51f0
+      gsl_test (s, "%s test_driver apply returned %d",
5a51f0
+                gsl_odeiv2_step_name (d->s), s);
5a51f0
+    }
5a51f0
+
5a51f0
+  gsl_test_rel (y[0], cos (tinit), d->n * tol,
5a51f0
+                "%s test_driver y0", gsl_odeiv2_step_name (d->s));
5a51f0
+  gsl_test_rel (y[1], sin (tinit), d->n * tol,
5a51f0
+                "%s test_driver y1", gsl_odeiv2_step_name (d->s));
5a51f0
+
5a51f0
   gsl_odeiv2_driver_free (d);
5a51f0
 
5a51f0
   /* Test that maximum number of steps is obeyed */
5a51f0
 
5a51f0
-  d = gsl_odeiv2_driver_alloc_y_new (&rhs_func_sin, gsl_odeiv2_step_rkf45,
5a51f0
-                                     1e-3, tol, tol);
5a51f0
+  d = gsl_odeiv2_driver_alloc_y_new (&rhs_func_sin, T, 1e-3, tol, tol);
5a51f0
   gsl_odeiv2_driver_set_hmax (d, hmax);
5a51f0
   gsl_odeiv2_driver_set_nmax (d, maxsteps);
5a51f0
 
5a51f0
@@ -2091,19 +2115,20 @@ test_driver (void)
5a51f0
 
5a51f0
   if (d->n != maxsteps + 1)
5a51f0
     {
5a51f0
-      gsl_test (1, "test_driver steps %d, expected %d", d->n, maxsteps + 1);
5a51f0
+      gsl_test (1, "%s test_driver steps %d, expected %d",
5a51f0
+                gsl_odeiv2_step_name (d->s), d->n, maxsteps + 1);
5a51f0
     }
5a51f0
   else
5a51f0
     {
5a51f0
-      gsl_test (0, "test_driver max steps test");
5a51f0
+      gsl_test (0, "%s test_driver max steps test",
5a51f0
+                gsl_odeiv2_step_name (d->s));
5a51f0
     }
5a51f0
 
5a51f0
   gsl_odeiv2_driver_free (d);
5a51f0
 
5a51f0
   /* Test that minimum step length is obeyed */
5a51f0
 
5a51f0
-  d = gsl_odeiv2_driver_alloc_y_new (&rhs_func_broken, gsl_odeiv2_step_rk8pd,
5a51f0
-                                     1e-3, tol, tol);
5a51f0
+  d = gsl_odeiv2_driver_alloc_y_new (&rhs_func_broken, T, 1e-3, tol, tol);
5a51f0
 
5a51f0
   gsl_odeiv2_driver_set_hmin (d, hmin);
5a51f0
   y[0] = 0.0;
5a51f0
@@ -2113,77 +2138,87 @@ test_driver (void)
5a51f0
 
5a51f0
   if (s != GSL_ENOPROG)
5a51f0
     {
5a51f0
-      gsl_test (1, "test_driver min step test returned %d", s);
5a51f0
+      gsl_test (1, "%s test_driver min step test returned %d",
5a51f0
+                gsl_odeiv2_step_name (d->s), s);
5a51f0
     }
5a51f0
   else
5a51f0
     {
5a51f0
-      gsl_test (0, "test_driver min step test");
5a51f0
+      gsl_test (0, "%s test_driver min step test",
5a51f0
+                gsl_odeiv2_step_name (d->s));
5a51f0
     }
5a51f0
 
5a51f0
   gsl_odeiv2_driver_free (d);
5a51f0
 
5a51f0
   /* Test negative integration direction */
5a51f0
 
5a51f0
-  d = gsl_odeiv2_driver_alloc_y_new (&rhs_func_sin, gsl_odeiv2_step_rkf45,
5a51f0
-                                     -1e-3, tol, tol);
5a51f0
+  d = gsl_odeiv2_driver_alloc_y_new (&rhs_func_sin, T, -1e-3, tol, tol);
5a51f0
 
5a51f0
   y[0] = 1.0;
5a51f0
   y[1] = 0.0;
5a51f0
   t = 2.5;
5a51f0
 
5a51f0
-  gsl_odeiv2_driver_set_nmax (d, 1000);
5a51f0
   s = gsl_odeiv2_driver_apply (d, &t, t3, y);
5a51f0
 
5a51f0
   {
5a51f0
-    const double tol = 1e-6;
5a51f0
+    const double tol = 1e-3;
5a51f0
     const double test = fabs (t - t3);
5a51f0
     const double val = fabs (sin (-5.0) - y[1]);
5a51f0
 
5a51f0
     if (test > GSL_DBL_EPSILON)
5a51f0
       {
5a51f0
         gsl_test (1,
5a51f0
-                  "test_driver negative dir diff %e, expected less than %e",
5a51f0
-                  test, GSL_DBL_EPSILON);
5a51f0
+                  "%s test_driver negative dir diff %e, expected less than %e",
5a51f0
+                  gsl_odeiv2_step_name (d->s), test, GSL_DBL_EPSILON);
5a51f0
       }
5a51f0
     else if (val > tol)
5a51f0
       {
5a51f0
-        gsl_test (1, "test_driver negative dir val %e, expected less than %e",
5a51f0
-                  val, tol);
5a51f0
+        gsl_test (1,
5a51f0
+                  "%s test_driver negative dir val %e, expected less than %e",
5a51f0
+                  gsl_odeiv2_step_name (d->s), val, tol);
5a51f0
       }
5a51f0
     else
5a51f0
       {
5a51f0
-        gsl_test (s, "test_driver negative direction test");
5a51f0
+        gsl_test (s, "%s test_driver negative direction test",
5a51f0
+                  gsl_odeiv2_step_name (d->s));
5a51f0
       }
5a51f0
   }
5a51f0
 
5a51f0
   /* Test driver_apply_fixed_step */
5a51f0
 
5a51f0
-  s = gsl_odeiv2_driver_apply_fixed_step (d, &t, 0.025, nfsteps, y);
5a51f0
+  gsl_odeiv2_driver_reset_hstart (d, 1e-3);
5a51f0
+  s = gsl_odeiv2_driver_apply_fixed_step (d, &t, hfixed, nfsteps, y);
5a51f0
+
5a51f0
+  if (s != GSL_SUCCESS)
5a51f0
+    {
5a51f0
+      gsl_test (s, "%s test_driver apply_fixed_step returned %d",
5a51f0
+                gsl_odeiv2_step_name (d->s), s);
5a51f0
+    }
5a51f0
 
5a51f0
   {
5a51f0
-    const double tol = 1e-6;
5a51f0
+    const double tol = 1e-3;
5a51f0
     const double val = fabs (sin (-2.5) - y[1]);
5a51f0
 
5a51f0
     if (fabs (t) > nfsteps * GSL_DBL_EPSILON)
5a51f0
       {
5a51f0
         gsl_test (1,
5a51f0
-                  "test_driver apply_fixed_step diff %e, expected less than %e",
5a51f0
-                  fabs (t), nfsteps * GSL_DBL_EPSILON);
5a51f0
+                  "%s test_driver apply_fixed_step t %e, expected less than %e",
5a51f0
+                  gsl_odeiv2_step_name (d->s), fabs (t),
5a51f0
+                  nfsteps * GSL_DBL_EPSILON);
5a51f0
       }
5a51f0
     else if (val > tol)
5a51f0
       {
5a51f0
         gsl_test (1,
5a51f0
-                  "test_driver apply_fixed_step val %e, expected less than %e",
5a51f0
-                  val, tol);
5a51f0
+                  "%s test_driver apply_fixed_step val %e, expected less than %e",
5a51f0
+                  gsl_odeiv2_step_name (d->s), val, tol);
5a51f0
       }
5a51f0
     else
5a51f0
       {
5a51f0
-        gsl_test (s, "test_driver apply_fixed_step test");
5a51f0
+        gsl_test (s, "%s test_driver apply_fixed_step test",
5a51f0
+                  gsl_odeiv2_step_name (d->s));
5a51f0
       }
5a51f0
   }
5a51f0
 
5a51f0
   gsl_odeiv2_driver_free (d);
5a51f0
-
5a51f0
 }
5a51f0
 
5a51f0
 void
5a51f0
@@ -2407,7 +2442,7 @@ main (void)
5a51f0
 {
5a51f0
 
5a51f0
   /* Benchmark routine to compare stepper performance */
5a51f0
-  /* benchmark_precision(); return 0;*/
5a51f0
+  /* benchmark_precision(); return 0; */
5a51f0
 
5a51f0
   /* Test single problem, for debugging purposes */
5a51f0
   /* test_evolve_temp (gsl_odeiv2_step_msadams, 1e-3, 1e-8); return 0; */
5a51f0
@@ -2453,10 +2488,6 @@ main (void)
5a51f0
   for (i = 0; p[i].type != 0; i++)
5a51f0
     {
5a51f0
       test_stepper (p[i].type);
5a51f0
-    }
5a51f0
-
5a51f0
-  for (i = 0; p[i].type != 0; i++)
5a51f0
-    {
5a51f0
       test_evolve_linear (p[i].type, p[i].h, 1e-10);
5a51f0
       test_evolve_exp (p[i].type, p[i].h, 1e-5);
5a51f0
       test_evolve_sin (p[i].type, p[i].h, 1e-8);
5a51f0
@@ -2468,6 +2499,7 @@ main (void)
5a51f0
       test_broken (p[i].type, p[i].h, 1e-8);
5a51f0
       test_stepsize_fail (p[i].type, p[i].h);
5a51f0
       test_user_break (p[i].type, p[i].h);
5a51f0
+      test_driver (p[i].type);
5a51f0
     }
5a51f0
 
5a51f0
   /* Derivative test for explicit steppers */
5a51f0
@@ -2493,14 +2525,12 @@ main (void)
5a51f0
     }
5a51f0
 
5a51f0
   /* Special tests */
5a51f0
-  
5a51f0
+
5a51f0
   test_nonstiff_problems ();
5a51f0
 
5a51f0
   test_stiff_problems ();
5a51f0
 
5a51f0
   test_extreme_problems ();
5a51f0
 
5a51f0
-  test_driver ();
5a51f0
-  
5a51f0
   exit (gsl_test_summary ());
5a51f0
 }
5a51f0
diff -up wrk/ode-initval2/TODO.wrk wrk/ode-initval2/TODO