source: trunk/examples/extended/electromagnetic/TestEm7/include/c2_function.hh @ 1337

Last change on this file since 1337 was 1337, checked in by garnier, 14 years ago

tag geant4.9.4 beta 1 + modifs locales

File size: 103.2 KB
Line 
1//
2// ********************************************************************
3// * License and Disclaimer                                           *
4// *                                                                  *
5// * The  Geant4 software  is  copyright of the Copyright Holders  of *
6// * the Geant4 Collaboration.  It is provided  under  the terms  and *
7// * conditions of the Geant4 Software License,  included in the file *
8// * LICENSE and available at  http://cern.ch/geant4/license .  These *
9// * include a list of copyright holders.                             *
10// *                                                                  *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work  make  any representation or  warranty, express or implied, *
14// * regarding  this  software system or assume any liability for its *
15// * use.  Please see the license in the file  LICENSE  and URL above *
16// * for the full disclaimer and the limitation of liability.         *
17// *                                                                  *
18// * This  code  implementation is the result of  the  scientific and *
19// * technical work of the GEANT4 collaboration.                      *
20// * By using,  copying,  modifying or  distributing the software (or *
21// * any work based  on the software)  you  agree  to acknowledge its *
22// * use  in  resulting  scientific  publications,  and indicate your *
23// * acceptance of all terms of the Geant4 Software license.          *
24// ********************************************************************
25//
26//
27/**
28 *  \file
29 *  \brief Provides the headers for the general c2_function algebra which supports
30 *  fast, flexible operations on piecewise-twice-differentiable functions
31 *
32 *  \author Created by R. A. Weller and Marcus H. Mendenhall on 7/9/05.
33 *  \author 2005 Vanderbilt University.
34 *
35 *      \version c2_function.hh,v 1.238 2008/05/22 12:45:19 marcus Exp
36 *  \see \ref c2_factory "Factory Functions" for information on constructing things in here 
37 */
38
39#ifndef __has_c2_function_hh
40#define __has_c2_function_hh 1
41
42// MSVC does not automatically define numerical constants such as M_PI without this.
43// this came from the msdn website, so it should be right...
44#ifdef _MSC_VER
45#define _USE_MATH_DEFINES
46#define c2_isnan _isnan
47#define c2_isfinite _finite
48#else
49#define c2_isnan std::isnan
50#define c2_isfinite std::isfinite
51#endif
52
53#include <cmath>
54#include <vector>
55#include <utility>
56#include <string>
57#include <stdexcept>
58#include <typeinfo>
59#include <sstream>
60
61/// \brief the exception class for c2_function operations.
62class c2_exception : public std::exception {
63public:
64    /// \brief construct the exception with an error message
65    /// \param msgcode the message
66    c2_exception(const char msgcode[]) : info(msgcode) { }
67    virtual ~c2_exception() throw() { }
68    /** Returns a C-style character string describing the general cause
69    *  of the current error.  */
70    virtual const char* what() const throw() { return info.c_str(); }
71private:
72    std::string info;
73};
74
75// put these forward references here, and with a bogus typename to make swig happy.
76template <typename float_type> class c2_composed_function_p;
77template <typename float_type> class c2_sum_p;
78template <typename float_type> class c2_diff_p;
79template <typename float_type> class c2_product_p;
80template <typename float_type> class c2_ratio_p;
81template <typename float_type> class c2_piecewise_function_p;
82template <typename float_type> class c2_quadratic_p;
83template <typename float_type> class c2_ptr;
84/**
85        \defgroup abstract_classes Abstract Classes
86        \defgroup arithmetic_functions Arithmetic Functions
87        \defgroup math_functions Mathemetical Functions
88        \defgroup parametric_functions Parametric Families of Functions
89        \defgroup interpolators Interpolating Functions
90        \defgroup containers Functions which are containers for, or functions of, other functions
91        \defgroup factories Factory classes which reduce silly template typing
92        \defgroup transforms Classes which provide coordinate system transformations, wih derivatives
93*/
94
95/// \brief structure used to hold evaluated function data at a point. 
96///
97/// Contains all the information for the function at one point.
98template <typename float_type> class c2_fblock 
99{       
100public:
101        /// \brief the abscissa
102        float_type x;
103        /// \brief the value of the function at \a x
104        float_type y;
105        /// \brief the derivative at \a x
106        float_type yp;
107        /// \brief the second derivative at \a x
108        float_type ypp; 
109        /// flag, filled in by c2_function::fill_fblock(), indicating the derivative is NaN of Inf
110        bool ypbad;
111        /// flag, filled in by c2_function::fill_fblock(), indicating the second derivative is NaN of Inf
112        bool yppbad; 
113};
114
115/**
116 \brief the parent class for all c2_functions.
117 \ingroup abstract_classes
118  c2_functions know their value, first, and second derivative at almost every point.
119  They can be efficiently combined with binary operators, via c2_binary_function,
120  composed via c2_composed_function_,
121  have their roots found via find_root(),
122  and be adaptively integrated via partial_integrals() or integral().
123  They also can carry information with them about how to find 'interesting' points on the function. 
124  This information is set with set_sampling_grid() and extracted with get_sampling_grid().
125
126  Particularly important subclasses are the interpolating functions classes,
127    interpolating_function , lin_log_interpolating_function, log_lin_interpolating_function,
128    log_log_interpolating_function, and arrhenius_interpolating_function,
129    as well as the template functions
130    inverse_integrated_density_function().
131 
132 For a discussion of memory management, see \ref memory_management
133 
134 */
135template <typename float_type=double> class c2_function {
136public:   
137    /// \brief get versioning information for the header file
138    /// \return the CVS Id string
139        const std::string cvs_header_vers() const { return 
140                "c2_function.hh,v 1.238 2008/05/22 12:45:19 marcus Exp";
141        }
142       
143    /// \brief get versioning information for the source file
144    /// \return the CVS Id string
145        const std::string cvs_file_vers() const ;
146       
147public:
148    /// \brief destructor
149        virtual ~c2_function() { 
150                if(sampling_grid && !no_overwrite_grid) delete sampling_grid;   
151                if(root_info) delete root_info; 
152                if(owner_count) {
153                        std::ostringstream outstr;
154                        outstr << "attempt to delete an object with non-zero ownership in class ";
155                        outstr << typeid(*this).name() << std::endl;
156                        throw c2_exception(outstr.str().c_str());
157                }
158        }
159       
160        /// \brief get the value and derivatives.
161    ///
162    /// There is required checking for null pointers on the derivatives,
163    /// and most implementations should operate faster if derivatives are not needed.
164    /// \param[in] x the point at which to evaluate the function
165    /// \param[out] yprime the first derivative (if pointer is non-null)
166    /// \param[out] yprime2 the second derivative (if pointer is non-null)
167    /// \return the value of the function
168        virtual float_type value_with_derivatives(float_type x, float_type *yprime, float_type *yprime2) const throw(c2_exception) =0 ; // { return 0; };
169       
170    /// \brief evaluate the function in the classic way, ignoring derivatives.
171    /// \param x the point at which to evaluate
172    /// \return the value of the function
173        inline float_type operator () (float_type x) const throw(c2_exception) 
174        { return value_with_derivatives(x, (float_type *)0, (float_type *)0); } 
175
176        /// \brief get the value and derivatives.
177    ///
178    /// \param[in] x the point at which to evaluate the function
179    /// \param[out] yprime the first derivative (if pointer is non-null)
180    /// \param[out] yprime2 the second derivative (if pointer is non-null)
181    /// \return the value of the function
182    inline float_type operator () (float_type x, float_type *yprime, float_type *yprime2) const throw(c2_exception) 
183        { return value_with_derivatives(x, yprime, yprime2); } 
184       
185        /// \brief solve f(x)==value very efficiently, with explicit knowledge of derivatives of the function
186        ///
187    /// find_root solves by iterated inverse quadratic extrapolation for a solution to f(x)=y.  It
188    /// includes checks against bad convergence, so it should never be able to fail.  Unlike typical
189    /// secant method or fancier Brent's method finders, this does not depend in any strong wasy on the
190    /// brackets, unless the finder has to resort to successive approximations to close in on a root.
191    /// Often, it is possible to make the brackets equal to the domain of the function, if there is
192    /// any clue as to where the root lies, as given by the parameter \a start. 
193    /// \param lower_bracket the lower bound for the search
194    /// \param upper_bracket the upper bound for the search.  Function sign must be
195    /// opposite to that at \a lower_bracket
196    /// \param start starting value for the search
197    /// \param value the value of the function being sought (solves f(x) = \a value)
198    /// \param[out] error If pointer is zero, errors raise exception. Otherwise, returns error here.
199    /// \param[out] final_yprime If pointer is not zero, return derivative of function at root
200    /// \param[out] final_yprime2 If pointer is not zero, return second derivative of function at root
201    /// \return the position of the root.
202        /// \see \ref rootfinder_subsec "Root finding sample"
203        float_type find_root(float_type lower_bracket, float_type upper_bracket, float_type start, 
204        float_type value, int *error=0, 
205        float_type *final_yprime=0, float_type *final_yprime2=0 ) const throw(c2_exception) ; // solve f(x)=value
206
207        /// \brief for points in xgrid, adaptively return Integral[f(x),{x,xgrid[i],xgrid[i+1]}] and return in vector, along with sum
208    ///
209        /// partial_integrals uses a method with an error O(dx**10) with full information from the derivatives,
210    /// and falls back to lower order methods if informed of incomplete derivatives.
211    /// It uses exact midpoint splitting of the intervals for recursion, resulting in no recomputation of the function
212    /// during recursive descent at previously computed points.
213    /// \param xgrid points between which to evaluate definite integrals. 
214    /// \param partials if non-NULL, a vector in which to receive the partial integrals.
215        /// It will automatically be sized apprpropriately, if provided, to contain \a n - 1 elements where \a n is the length of \a xgrid 
216    /// \param abs_tol the absolute error bound for each segment
217    /// \param rel_tol the fractional error bound for each segment. 
218    /// If the error is smaller than either the relative or absolute tolerance, the integration step is finished.
219    /// \param derivs number of derivatives to trust, which sets the order of the integrator.  The order
220    /// is 3*\a derivs + 4. \a derivs can be 0, 1, or 2.
221    /// \param adapt if true, use recursive adaptation, otherwise do simple evaluation on the grid provided
222    /// with no error checking.
223    /// \param extrapolate if true, use simple Richardson extrapolation on the final 2 steps to reduce the error.
224    /// \return sum of partial integrals, which is the definite integral from the first value in \a xgrid to the last.
225        float_type partial_integrals(std::vector<float_type> xgrid, std::vector<float_type> *partials = 0,
226          float_type abs_tol=1e-12, float_type rel_tol=1e-12, int derivs=2, bool adapt=true, bool extrapolate=true) 
227                const throw(c2_exception);
228       
229    /// \brief a fully-automated integrator which uses the information provided by the get_sampling_grid() function
230    /// to figure out what to do.
231        ///
232        /// It returns the integral of the function over the domain requested
233    /// with error tolerances as specified.  It is just a front-end to partial_integrals()
234    ///
235    /// \param xmin lower bound of the domain for integration
236        /// \param xmax upper bound of the domain for integration
237    /// \param partials if non-NULL, a vector in which to receive the partial integrals.
238        /// It will automatically be sized appropriately, if provided, to contain \a n - 1 elements where \a n is the length of \a xgrid 
239    /// \param abs_tol the absolute error bound for each segment
240    /// \param rel_tol the fractional error bound for each segment. 
241    /// If the error is smaller than either the relative or absolute tolerance, the integration step is finished.
242    /// \param derivs number of derivatives to trust, which sets the order of the integrator.  The order
243    /// is 3*\a derivs + 4. \a derivs can be 0, 1, or 2.
244    /// \param adapt if true, use recursive adaptation, otherwise do simple evaluation on the grid provided
245    /// with no error checking.
246    /// \param extrapolate if true, use simple Richardson extrapolation on the final 2 steps to reduce the error.
247    /// \return sum of partial integrals, which is the definite integral from the first value in \a xgrid to the last.
248        float_type integral(float_type xmin, float_type xmax, std::vector<float_type> *partials = 0,
249             float_type abs_tol=1e-12, float_type rel_tol=1e-12, int derivs=2, bool adapt=true, bool extrapolate=true) 
250                const throw(c2_exception);
251
252        /// \brief create a c2_piecewise_function_p from c2_connector_function_p segments which
253        /// is a representation of the parent function to the specified accuracy, but maybe much cheaper to evaluate
254        ///
255        /// This method has three modes, depending on the \a derivs flag.
256        ///
257        /// If \a derivs is 2,
258        /// it computes a c2_piecewise_function_p representation of its parent function, which may be a much faster
259        /// function to use in codes if the parent function is expensive.  If \a xvals and \a yvals are non-null,
260        /// it will also fill them in with the function values at each grid point the adaptive algorithm chooses.
261        ///
262        /// If \a derivs is 1, this does not create the connectors,
263        /// and returns an null pointer, but will fill in the \a xvals and \a yvals
264        /// vectors with values of the function at points such that the linear interpolation error between the points
265        /// is bounded by the tolerance values given.  Because it uses derivative information from the function to manage the
266        /// error control, it is almost completely free of issues with missing periods of oscillatory functions,
267        /// even with no information provided in the sampling grid.
268        /// This is typically useful for sampling a function for plotting.
269        ///
270        /// If \a derivs is 0, this does something very like what it does if \a derivs = 1, but without derivatives. 
271        /// Instead, to compute the intermediate value of the function for error control, it just uses
272        /// 3-point parabolic interpolation.  This is useful amost exclusively for converting a non-c2_function,
273        /// with no derivatives, but wrapped in a c2_classic_function wrapper, into a table of values to seed an interpolating_function_p.
274        /// Note, however, that without derivatives, this is very susceptible to missing periods of oscillatory
275        /// functions, so it is important to set a sampling grid which isn't too much coarser than the typical oscillations.
276        ///
277        /// \note the \a sampling_grid of the returned function matches the \a sampling_grid of its parent.
278        /// \see \ref sample_function_for_plotting "Adaptive Sampling Examples"
279    /// \param xmin lower bound of the domain for sampling
280        /// \param xmax upper bound of the domain for sampling
281    /// \param abs_tol the absolute error bound for each segment
282    /// \param rel_tol the fractional error bound for each segment.
283        /// \param derivs if 0 or 1, return a useless function, but fill in the \a xvals and \a yvals vectors (if non-null).
284        /// Also, if 0 or 1, tolerances refer to linear interpolation, not high-order interpolation.
285        /// If 2, return a full piecewise collection of c2_connector_function_p segments.  See discussion above.
286        /// \param [in,out] xvals vector of abscissas at which the function was actually sampled (if non-null)
287        /// \param [in,out] yvals vector of function values corresponding to \a xvals (if non-null)
288        /// \return a new, sampled representation, if \a derivs is 2.  A null pointer if \a derivs is 0 or 1.
289        c2_piecewise_function_p<float_type> *adaptively_sample(float_type xmin, float_type xmax,
290                 float_type abs_tol=1e-12, float_type rel_tol=1e-12,
291                 int derivs=2, std::vector<float_type> *xvals=0, std::vector<float_type> *yvals=0) const throw(c2_exception);
292       
293        /// \brief return the lower bound of the domain for this function as set by set_domain()
294        inline float_type xmin() const { return fXMin; }
295        /// \brief return the upper bound of the domain for this function as set by set_domain()
296        inline float_type xmax() const { return fXMax; }
297        /// \brief set the domain for this function.
298        void set_domain(float_type xmin, float_type xmax) { fXMin=xmin; fXMax=xmax; }
299               
300        /// \brief this is a counter owned by the function but which can be used to monitor efficiency of algorithms.
301        ///
302        /// It is not maintained automatically in general!  The root finder, integrator, and sampler do increment it.
303        /// \return number of evaluations logged since last reset.
304        size_t get_evaluations() const { return evaluations; }
305        /// \brief reset the counter
306        void reset_evaluations()  const { evaluations=0; } // evaluations are 'invisible' to constant
307        /// \brief count evaluations
308        inline void increment_evaluations() const { evaluations++; }
309       
310        /// \brief check that a vector is monotonic, throw an exception if not, and return a flag if it is reversed
311        ///
312        /// \param data a vector of data points which are expected to be monotonic.
313        /// \param message an informative string to include in an exception if this throws c2_exception
314        /// \return true if in decreasing order, false if increasing
315        bool check_monotonicity(const std::vector<float_type> &data, const char message[]) const throw(c2_exception);
316       
317        /// \brief establish a grid of 'interesting' points on the function.
318        ///
319        /// The sampling grid describes a reasonable initial set of points to look at the function.
320    /// this should generally be set at a scale which is quite coarse, and sufficient for initializing
321    /// adaptive integration or possibly root bracketing. For sampling a function to build a new interpolating
322    /// function, one may want to refine this for accuracy.  However, interpolating_functions themselves
323    /// return their original X grid by default, so refining the grid in this case might be a bad idea.
324        /// \param grid a vector of abscissas.  The contents is copied into an internal vector, so the \a grid can be discarded after passingin.
325        virtual void set_sampling_grid(const std::vector<float_type> &grid) throw(c2_exception); 
326       
327        /// \brief get the sampling grid, which may be a null pointer
328        /// \return pointer to the sampling grid
329        std::vector<float_type> *get_sampling_grid_pointer() const { return sampling_grid; } 
330       
331    /// \brief return the grid of 'interesting' points along this function which lie in the region requested
332        ///
333    /// if a sampling grid is defined, work from there, otherwise return vector of (xmin, xmax)
334        /// \param xmin the lower bound for which the function is to be sampled
335        /// \param xmax the upper bound for which the function is to be sampled
336        /// \param [in,out] grid filled vector containing the samplng grid.
337        virtual void get_sampling_grid(float_type xmin, float_type xmax, std::vector<float_type> &grid) const ;
338       
339        /// \brief clean up endpoints on a grid of points
340        /// \param[in,out] result the sampling grid with excessively closely space endpoints removed.
341        /// The grid is modified in place.
342        void preen_sampling_grid(std::vector<float_type> *result) const;               
343        /// \brief refine a grid by splitting each interval into more intervals
344        /// \param [in,out] grid the grid to refine in place
345        /// \param refinement the number of new steps for each old step
346        void refine_sampling_grid(std::vector<float_type> &grid, size_t refinement) const;             
347       
348        /// \brief create a new c2_function from this one which is normalized on the interval
349    /// \param xmin lower bound of the domain for integration
350        /// \param xmax upper bound of the domain for integration
351        /// \param norm the desired integral for the function over the region
352        /// \return a new c2_function with the desired \a norm.
353        c2_function<float_type> &normalized_function(float_type xmin, float_type xmax, float_type norm=1.0) const throw(c2_exception);
354        /// \brief create a new c2_function from this one which is square-normalized on the interval
355    /// \param xmin lower bound of the domain for integration
356        /// \param xmax upper bound of the domain for integration
357        /// \param norm the desired integral for the function over the region
358        /// \return a new c2_function with the desired \a norm.
359        c2_function<float_type> &square_normalized_function(float_type xmin, float_type xmax, float_type norm=1.0) const throw(c2_exception);
360        /// \brief create a new c2_function from this one which is square-normalized with the provided \a weight on the interval
361    /// \param xmin lower bound of the domain for integration
362        /// \param xmax upper bound of the domain for integration
363        /// \param weight a c2_function providing the weight
364        /// \param norm the desired integral for the function over the region
365        /// \return a new c2_function with the desired \a norm.
366        c2_function<float_type> &square_normalized_function(
367                float_type xmin, float_type xmax, const c2_function<float_type> &weight, float_type norm=1.0)
368                const throw(c2_exception);
369
370        /// \brief factory function to create a c2_sum_p from a regular algebraic expression.
371        /// \param rhs the right-hand term of the sum
372        /// \return a new c2_function
373        c2_sum_p<float_type> &operator + (const c2_function<float_type> &rhs)  const 
374                { return *new c2_sum_p<float_type>(*this, rhs); }
375        /// \brief factory function to create a c2_diff_p from a regular algebraic expression.
376        /// \param rhs the right-hand term of the difference
377        /// \return a new c2_function
378        c2_diff_p<float_type> &operator - (const c2_function<float_type> &rhs)  const 
379                { return *new c2_diff_p<float_type>(*this, rhs); }
380        /// \brief factory function to create a c2_product_p from a regular algebraic expression.
381        /// \param rhs the right-hand term of the product
382        /// \return a new c2_function
383        c2_product_p<float_type> &operator * (const c2_function<float_type> &rhs) const 
384                { return *new c2_product_p<float_type>(*this, rhs); }
385        /// \brief factory function to create a c2_ratio_p from a regular algebraic expression.
386        /// \param rhs the right-hand term of the ratio (the denominator)
387        /// \return a new c2_function
388        c2_ratio_p<float_type> &operator / (const c2_function<float_type> &rhs)  const 
389                { return *new c2_ratio_p<float_type>(*this, rhs); }
390    /// \brief compose this function outside another.
391    /// \param inner the inner function
392    /// \return the composed function
393        /// \anchor compose_operator
394        c2_composed_function_p<float_type> & operator ()(const c2_function<float_type> &inner) const 
395                { return *new c2_composed_function_p<float_type>((*this), inner); }
396
397        /// \brief Find out where a calculation ran into trouble, if it got a nan.
398        /// If the most recent computation did not return a nan, this is undefined.
399        /// \return \a x value of point at which something went wrong, if integrator (or otherwise) returned a nan.
400        float_type get_trouble_point() const { return bad_x_point; }
401       
402        /// \brief increment our reference count.  Destruction is only legal if the count is zero.
403        void claim_ownership() const { owner_count++; }
404        /// \brief decrement our reference count. Do not destroy at zero.
405        /// \return final owner count, to check whether object should disappear.
406        size_t release_ownership_for_return() const throw(c2_exception) { 
407                if(!owner_count) {
408                        std::ostringstream outstr;
409                        outstr << "attempt to release ownership of an unowned function in class ";
410                        outstr << typeid(*this).name() << std::endl;
411                        throw c2_exception(outstr.str().c_str());
412                }
413                owner_count--; 
414                return owner_count;
415        }
416        /// \brief decrement our reference count. If the count reaches zero, destroy ourself.
417        void release_ownership() const throw(c2_exception) { 
418                if(!release_ownership_for_return()) delete this;
419        }
420        /// \brief get the reference count, mostly for debugging
421        /// \return the count
422        size_t count_owners() const { return owner_count; }
423
424protected:
425        c2_function(const c2_function<float_type>  &src) : sampling_grid(0),
426                no_overwrite_grid(false),
427        fXMin(src.fXMin), fXMax(src.fXMax), root_info(0), owner_count(0)
428        {} // copy constructor only copies domain, and is only for internal use
429        c2_function() : 
430                        sampling_grid(0), no_overwrite_grid(0), 
431        fXMin(-std::numeric_limits<float_type>::max()), 
432        fXMax(std::numeric_limits<float_type>::max()), root_info(0), owner_count(0)
433                {} // prevent accidental naked construction (impossible any since this has pure virtual methods)
434       
435        // this should only be called very early on, by a constructor, before anyone else
436        // sets a sampling grid, or it will leak memory
437        virtual void set_sampling_grid_pointer(std::vector<float_type> &grid) 
438                { 
439                        if (sampling_grid && !no_overwrite_grid) delete sampling_grid; // grid was ours, lose it.
440                        sampling_grid=&grid; no_overwrite_grid=1; 
441                }
442       
443        std::vector<float_type> * sampling_grid;
444        bool no_overwrite_grid;
445       
446        float_type fXMin, fXMax;
447        mutable size_t evaluations;
448        /// \brief this point may be used to record where a calculation ran into trouble
449        mutable float_type bad_x_point;
450public: 
451        /// \brief fill in a c2_fblock<float_type>... a shortcut for the integrator & sampler
452        /// \param [in,out] fb the block to fill in with information
453        inline void fill_fblock(c2_fblock<float_type> &fb) const throw(c2_exception) 
454        {
455                fb.y=value_with_derivatives(fb.x, &fb.yp, &fb.ypp);
456                fb.ypbad=c2_isnan(fb.yp) || !c2_isfinite(fb.yp);
457                fb.yppbad=c2_isnan(fb.ypp) || !c2_isfinite(fb.ypp);
458                increment_evaluations();
459        }
460
461private:
462        /// \brief the data element for the internal recursion stack for the sampler and integrator
463        struct recur_item { 
464                c2_fblock<float_type> f1; size_t depth; 
465                float_type previous_estimate, abs_tol, step_sum; 
466                bool done; 
467                size_t f0index, f2index;
468        };
469       
470
471        /// \brief structure used to pass information recursively in integrator.
472        ///
473        /// the \a abs_tol is scaled by a factor of two at each division. 
474        /// Everything else is just passed down.
475        struct c2_integrate_recur { 
476                c2_fblock<float_type> *f0, *f1;
477                float_type abs_tol, rel_tol, eps_scale, extrap_coef, extrap2, dx_tolerance, abs_tol_min;
478                std::vector< recur_item > *rb_stack;
479                int  derivs;
480                bool adapt, extrapolate, inited;
481        };
482
483        /// \brief structure used to pass information recursively in sampler.
484        ///
485        struct c2_sample_recur { 
486                c2_fblock<float_type> *f0, *f1;
487                float_type abs_tol, rel_tol, dx_tolerance, abs_tol_min;
488                int derivs;
489                c2_piecewise_function_p<float_type> *out;
490                std::vector<float_type> *xvals, *yvals;
491                std::vector< recur_item > *rb_stack;
492                bool inited;
493        };
494
495        /// \brief structure used to hold root bracketing information
496        ///
497        struct c2_root_info {
498                c2_fblock<float_type> lower, upper;
499                bool inited;
500        };
501       
502    /// \brief Carry out the recursive subdivision and integration.
503    ///
504    /// This passes information recursively through the \a recur block pointer
505    /// to allow very efficient recursion.
506    /// \param rb a pointer to the recur struct.
507        float_type integrate_step(struct c2_integrate_recur &rb) const throw(c2_exception);
508   
509    /// \brief Carry out the recursive subdivision for sampling.
510    ///
511    /// This passes information recursively through the \a recur block pointer
512    /// to allow very efficient recursion.
513    /// \param rb a pointer to the recur struct.
514        void sample_step(struct c2_sample_recur &rb) const throw(c2_exception);
515
516    /// this carry a memory of the last root bracketing,
517    /// to avoid the necessity of evaluating the function on the brackets every time
518    /// if the brackets have not been changed.
519        /// it is declared as a pointer, since many c2_functions may never need one allocated
520    mutable struct  c2_root_info *root_info;
521       
522        mutable size_t owner_count;
523};
524
525/// \brief a container into which any conventional c-style function can be dropped,
526/// to create a degenerate c2_function without derivatives.
527/// Mostly useful for sampling into interpolating functions.
528/// construct a reference to this with c2_classic_function()
529/// \ingroup containers
530/// The factory function c2_factory::classic_function() creates *new c2_classic_function_p()
531template <typename float_type=double> class c2_classic_function_p : public c2_function<float_type> {
532public:
533        /// \brief construct the container
534        /// \param c_func a pointer to a conventional c-style function
535        c2_classic_function_p(const float_type (*c_func)(float_type)) : c2_function<float_type>(), func(c_func)  {}
536
537        /// \copydoc c2_function::value_with_derivatives
538        /// Uses the internal function pointer set by set_function().
539        virtual float_type value_with_derivatives(float_type x, float_type *yprime, float_type *yprime2) const throw(c2_exception) 
540        {
541                if(!func) throw c2_exception("c2_classic_function called with null function");
542                if(yprime) *yprime=0;
543                if(yprime2) *yprime2=0;
544                return func(x); 
545        }
546        ~c2_classic_function_p() { }
547       
548protected:
549        /// \brief pointer to our function
550        const float_type (*func)(float_type);
551};
552
553/// \brief create a container for a c2_function which handles the reference counting.
554/// \ingroup containers
555/// It is useful as a smart container to hold a c2_function and keep the reference count correct. 
556/// The recommended way for a class to store a c2_function which is handed in from the outside
557/// is for it to have a c2_ptr member into which the passed-in function is stored.
558/// This way, when the class instance is deleted, it will automatically dereference any function
559/// which it was handed.
560///
561/// This class contains a copy constructor and operator=, to make it fairly easy to make
562/// a std::vector of these objects, and have it work as expected.
563template <typename float_type> class c2_const_ptr {
564public:
565        /// \brief construct the container with no function
566        c2_const_ptr() : func(0)  {}
567        /// \brief construct the container with a pre-defined function
568        /// \param f the function to store
569        c2_const_ptr(const c2_function<float_type> &f) : func(0) 
570                { set_function(&f); }
571        /// \brief copy constructor
572        /// \param src the container to copy
573        c2_const_ptr(const c2_const_ptr<float_type> &src) : func(0)
574                { set_function(src.get_ptr()); }
575        /// \brief fill the container with a new function, or clear it with a null pointer
576        /// \param f the function to store, releasing any previously held function
577        void set_function(const c2_function<float_type> *f) 
578        { 
579                if(func) func->release_ownership();
580                func=f; 
581                if(func) func->claim_ownership();
582        }
583       
584        /// \brief fill the container from another container
585        /// \param f the container to copy
586        void operator =(const c2_const_ptr<float_type> &f) 
587                { set_function(f.get_ptr()); }
588        /// \brief fill the container with a function
589        /// \param f the function
590        void operator =(const c2_function<float_type> &f) 
591                { set_function(&f); }
592        /// \brief release the function without destroying it, so it can be returned from a function
593        ///
594        /// This is usually the very last line of a function before the return statement, so that
595        /// any exceptions that happen during execution of the function will cause proper cleanup.
596        /// Once the function has been released from its container this way, it is an orhpaned object
597        /// until the caller claims it, so it could get lost if an exception happens.
598        void release_for_return() throw(c2_exception)
599                {       
600                        if(func) func->release_ownership_for_return();
601                        func=0;
602                }
603        /// \brief clear the function
604        ///
605        /// Any attempt to use this c2_plugin_function_p throws an exception if the saved function is cleared.
606        void unset_function(void) { set_function(0);  }
607        /// \brief destructor
608        ~c2_const_ptr() { set_function(0); }
609       
610        /// \brief get a reference to our owned function
611        inline const c2_function<float_type> &get() const throw(c2_exception) 
612        { 
613                if(!func) throw c2_exception("c2_ptr accessed uninitialized");
614                return *func;
615        }
616        /// \brief get an unchecked pointer to our owned function
617        inline const c2_function<float_type> *get_ptr() const { return func; }
618        /// \brief get a checked pointer to our owned function
619        inline const c2_function<float_type> *operator -> () const 
620                { return &get(); }
621        /// \brief check if we have a valid function
622        bool valid() const { return func != 0; }
623       
624        /// \brief type coercion operator which lets us use a pointer as if it were a const c2_function
625        operator const c2_function<float_type>& () const { return this->get(); }
626       
627        /// \brief convenience operator to make us look like a function
628        /// \param x the value at which to evaluate the contained function
629        /// \return the evaluated function
630        /// \note If you using this repeatedly, do const c2_function<float_type> &func=ptr;
631        /// and use func(x).  Calling this operator wastes some time, since it checks the validity of the
632        /// pointer every time.
633        float_type operator()(float_type x) const throw(c2_exception) { return get()(x); }
634        /// \brief convenience operator to make us look like a function
635        /// \param x the value at which to evaluate the contained function
636        /// \param yprime the derivative
637        /// \param yprime2 the second derivative
638        /// \return the evaluated function
639        /// \note If you using this repeatedly, do const c2_function<float_type> &func=ptr;
640        /// and use func(x).  Calling this operator wastes some time, since it checks the validity of the
641        /// pointer every time.
642        float_type operator()(float_type x, float_type *yprime, float_type *yprime2) const throw(c2_exception) 
643                { return get().value_with_derivatives(x, yprime, yprime2); }
644        /// \brief factory function to create a c2_sum_p from a regular algebraic expression.
645        /// \param rhs the right-hand term of the sum
646        /// \return a new c2_function
647        c2_sum_p<float_type> &operator + (const c2_function<float_type> &rhs)  const throw(c2_exception)
648                { return *new c2_sum_p<float_type>(get(), rhs); }
649        /// \brief factory function to create a c2_diff_p from a regular algebraic expression.
650        /// \param rhs the right-hand term of the difference
651        /// \return a new c2_function
652        c2_diff_p<float_type> &operator - (const c2_function<float_type> &rhs)  const throw(c2_exception)
653                { return *new c2_diff_p<float_type>(get(), rhs); }
654        /// \brief factory function to create a c2_product_p from a regular algebraic expression.
655        /// \param rhs the right-hand term of the product
656        /// \return a new c2_function
657        c2_product_p<float_type> &operator * (const c2_function<float_type> &rhs) const throw(c2_exception)
658                { return *new c2_product_p<float_type>(get(), rhs); }
659        /// \brief factory function to create a c2_ratio_p from a regular algebraic expression.
660        /// \param rhs the right-hand term of the ratio (the denominator)
661        /// \return a new c2_function
662        c2_ratio_p<float_type> &operator / (const c2_function<float_type> &rhs)  const throw(c2_exception)
663                { return *new c2_ratio_p<float_type>(get(), rhs); }
664    /// \brief compose this function outside another.
665    /// \param inner the inner function
666    /// \return the composed function
667        c2_composed_function_p<float_type> & operator ()(const c2_function<float_type> &inner) const throw(c2_exception)
668                { return *new c2_composed_function_p<float_type>(get(), inner); }
669       
670protected:
671        const c2_function<float_type> * func;
672};
673
674/// \brief create a container for a c2_function which handles the reference counting.
675/// \ingroup containers
676///
677/// \see  c2_const_ptr and \ref memory_management "Use of c2_ptr for memory management"
678
679template <typename float_type> class c2_ptr : public c2_const_ptr<float_type >
680{
681public:
682        /// \brief construct the container with no function
683        c2_ptr() : c2_const_ptr<float_type>()  {}
684        /// \brief construct the container with a pre-defined function
685        /// \param f the function to store
686        c2_ptr(c2_function<float_type> &f) : 
687                c2_const_ptr<float_type>() { set_function(&f); } 
688        /// \brief copy constructor
689        /// \param src the container to copy
690        c2_ptr(const c2_ptr<float_type> &src) : 
691                c2_const_ptr<float_type>() { set_function(src.get_ptr()); }
692        /// \brief get a checked pointer to our owned function
693        inline c2_function<float_type> &get() const throw(c2_exception) 
694                { return *const_cast<c2_function<float_type>*>(&c2_const_ptr<float_type>::get()); }
695        /// \brief get an unchecked pointer to our owned function
696        inline c2_function<float_type> *get_ptr() const 
697                { return const_cast<c2_function<float_type>*>(this->func); }
698        /// \brief get a checked pointer to our owned function
699        inline c2_function<float_type> *operator -> () const 
700                { return &get(); }
701        /// \brief fill the container from another container
702        /// \param f the container to copy
703        void operator =(const c2_ptr<float_type> &f) 
704                { set_function(f.get_ptr()); }
705        /// \brief fill the container with a function
706        /// \param f the function
707        void operator =(c2_function<float_type> &f) 
708                { set_function(&f); }
709private:
710        /// \brief hidden non-const-safe version of operator=
711        void operator =(const c2_const_ptr<float_type> &f) { }
712        /// \brief hidden non-const-safe version of operator=
713        void operator =(const c2_function<float_type> &f) { }
714};
715
716/// \brief create a non-generic container for a c2_function which handles the reference counting.
717/// \ingroup containers
718///
719/// \see  c2_const_ptr and \ref memory_management "Use of c2_ptr for memory management"
720///
721/// \note Overuse of this class will generate massive bloat.  Use c2_ptr and c2_const_ptr if you don't _really_ need specific pointer types.
722/// \see  \ref memory_management "Use of c2_ptr for memory management"
723/*
724template <typename float_type, template <typename> class c2_class > class c2_typed_ptr : public c2_const_ptr<float_type> {
725public:
726        /// \brief construct the container with no function
727        c2_typed_ptr() : c2_ptr<float_type>()  {}
728        /// \brief construct the container with a pre-defined function
729        /// \param f the function to store
730        c2_typed_ptr(c2_class<float_type> &f)
731                : c2_const_ptr<float_type>() { this->set_function(&f); }
732        /// \brief copy constructor
733        /// \param src the container to copy
734        c2_typed_ptr(const c2_typed_ptr<float_type, c2_class> &src)
735                : c2_const_ptr<float_type>() { this->set_function(src.get_ptr()); }
736       
737        /// \brief get a reference to our owned function
738        inline c2_class<float_type> &get() const throw(c2_exception)
739                {
740                        return *static_cast<c2_class<float_type> *>(const_cast<c2_function<float_type>*>(&c2_const_ptr<float_type>::get()));
741                }
742        /// \brief get a checked pointer to our owned function
743        inline c2_class<float_type> *operator -> () const
744                { return &get(); }
745        /// \brief get an unchecked pointer to our owned function
746        inline c2_class<float_type> *get_ptr() const
747                { return static_cast<c2_class<float_type> *>(const_cast<c2_function<float_type>*>(this->func)); }
748        /// \brief type coercion operator which lets us use a pointer as if it were a c2_function
749        operator c2_class<float_type>&() const { return get(); }
750        /// \brief fill the container from another container
751        /// \param f the container to copy
752        void operator =(const c2_typed_ptr<float_type, c2_class> &f)
753                { set_function(f.get_ptr()); }
754        /// \brief fill the container with a function
755        /// \param f the function
756        void operator =(c2_class<float_type> &f)
757                { set_function(&f); }
758private:
759        /// \brief hidden downcasting version of operator=
760        void operator =(const c2_const_ptr<float_type> &f) { }
761        /// \brief hidden downcasting version of operator=. Use an explicit dynamic_cast<c2_class<float_type>&>(f) if you need to try this.
762        void operator =(const c2_function<float_type> &f) { }
763};
764*/
765/// \brief a container into which any other c2_function can be dropped, to allow expressions
766/// with replacable components. 
767/// \ingroup containers
768///It is useful for plugging different InterpolatingFunctions into a c2_function expression.
769///It saves a lot of effort in other places with casting away const declarations.
770///
771/// It is also useful as a wrapper for a function if it is necessary to have a copy of a function
772/// which has a different domain or sampling grid than the parent function.  This can be
773/// be used, for example, to patch badly-behaved functions with c2_piecewise_function_p by
774/// taking the parent function, creating two plugins of it with domains on each side of the
775/// nasty bit, and then inserting a nice function in the hole.
776///
777/// This can also be used as a fancier c2_ptr which allows direct evaluation
778/// instead of having to dereference the container first.
779///
780/// The factory function c2_factory::plugin_function() creates *new c2_plugin_function_p()
781template <typename float_type=double> class c2_plugin_function_p : 
782        public c2_function<float_type> {
783public:
784        /// \brief construct the container with no function
785        c2_plugin_function_p() : c2_function<float_type>(), func()  {}
786        /// \brief construct the container with a pre-defined function
787        c2_plugin_function_p(c2_function<float_type> &f) : 
788                c2_function<float_type>(),func(f)  { }
789        /// \brief fill the container with a new function, or clear it with a null pointer
790        /// and copy our domain
791        void set_function(c2_function<float_type> *f) 
792                {
793                        func.set_function(f);
794                        if(f) set_domain(f->xmin(), f->xmax());
795                }
796        /// \copydoc c2_function::value_with_derivatives
797        /// Uses the internal function pointer set by set_function().
798        virtual float_type value_with_derivatives(float_type x, float_type *yprime, float_type *yprime2) const throw(c2_exception) 
799                {
800                        if(!func.valid()) throw c2_exception("c2_plugin_function_p called uninitialized");
801                        return func->value_with_derivatives(x, yprime, yprime2); 
802                }
803        /// \brief destructor
804        ~c2_plugin_function_p() { }
805       
806        /// \brief clear our function
807        void unset_function() { func.unset_function(); }
808       
809        virtual void get_sampling_grid(float_type xmin, float_type xmax, std::vector<float_type> &grid) const 
810        {       
811                if(!func.valid()) throw c2_exception("c2_plugin_function_p called uninitialized");
812                if(this->sampling_grid) c2_function<float_type>::get_sampling_grid(xmin, xmax, grid);
813                else  func->get_sampling_grid(xmin, xmax, grid);
814        }
815protected:
816        c2_ptr<float_type> func;
817};
818
819/// \brief a c2_plugin_function_p which promises not to fiddle with the plugged function.
820/// \ingroup containers
821///
822/// The factory function c2_factory::const_plugin_function() creates *new c2_const_plugin_function_p()
823template <typename float_type=double> class c2_const_plugin_function_p : public c2_plugin_function_p<float_type> {
824public:
825        /// \brief construct the container with no function
826        c2_const_plugin_function_p() : c2_plugin_function_p<float_type>()  {}
827        /// \brief construct the container with a pre-defined function
828        c2_const_plugin_function_p(const c2_function<float_type> &f) : 
829                c2_plugin_function_p<float_type>()  { set_function(&f); }
830        /// \brief fill the container with a new function, or clear it with a null pointer
831        void set_function(const c2_function<float_type> *f) 
832                { c2_plugin_function_p<float_type>::set_function(const_cast<c2_function<float_type>*>(f)); }
833        /// \brief destructor
834        ~c2_const_plugin_function_p() { }
835       
836        /// \brief get a const reference to our owned function, for direct access
837        const c2_function<float_type> &get() const throw(c2_exception) 
838                { return this->func.get(); }
839};
840
841/// \brief Provides support for c2_function objects which are constructed from two other c2_function
842/// objects. 
843/// \ingroup abstract_classes
844template <typename float_type=double> class c2_binary_function : public c2_function<float_type> {
845public:
846        ///  \brief function to manage the binary operation, used by c2_binary_function::value_with_derivatives()
847    ///
848       
849        virtual float_type value_with_derivatives(float_type x, float_type *yprime, float_type *yprime2) const throw (c2_exception) 
850    { 
851                if(stub) throw c2_exception("attempt to evaluate a c2_binary_function stub");
852                return this->combine(*Left.get_ptr(), *Right.get_ptr(), x, yprime, yprime2);
853    }
854
855        /// \brief destructor releases ownership of member functions
856        ///
857        virtual ~c2_binary_function() { }
858
859protected:
860        /// \brief construct the binary function
861        /// \param combiner pointer to the function which actualy knows how to execute the binary
862        /// \param left the c2_function to be used in the left side of the binary relation
863        /// \param right the c2_function to be used in the right side of the binary relation
864        c2_binary_function( 
865                        float_type (*combiner)(const c2_function<float_type> &left, const c2_function<float_type> &right, 
866                                   float_type x, float_type *yprime, float_type *yprime2),                                             
867                        const c2_function<float_type> &left,  const c2_function<float_type> &right) : 
868                        c2_function<float_type>(), combine(combiner), Left(left), Right(right), stub(false)
869        { 
870                set_domain(
871                                   (left.xmin() > right.xmin()) ? left.xmin() : right.xmin(), 
872                                   (left.xmax() < right.xmax()) ? left.xmax() : right.xmax()
873                                   );
874        } 
875       
876        /// \brief construct a 'stub' c2_binary_function, which provides access to the combine() function
877        /// \note Do not evaluate a 'stub' ever.  It is only used so that combine() can be called
878    c2_binary_function(
879           float_type (*combiner)(const c2_function<float_type> &left, const c2_function<float_type> &right, 
880                                                          float_type x, float_type *yprime, float_type *yprime2)
881                ) : c2_function<float_type>(), combine(combiner), Left(), Right(), stub(true) { }
882       
883public:
884        float_type (* const combine)(const c2_function<float_type> &left, const c2_function<float_type> &right, 
885                                                                 float_type x, float_type *yprime, float_type *yprime2);
886       
887protected:     
888        const c2_const_ptr<float_type> Left,  Right;
889        /// \brief if true, we don't own any functions, we are just a source of a combining function.
890        bool stub;
891       
892};
893
894/// \brief Create a very lightweight method to return a scalar multiple of another function.
895/// \ingroup containers \ingroup arithmetic_functions \ingroup parametric_functions
896///
897/// The factory function c2_factory::scaled_function() creates *new c2_scaled_function_p
898template <typename float_type=double> class c2_scaled_function_p : public c2_function<float_type> {
899public:
900        /// \brief construct the function with its scale factor.
901        ///
902        /// \param outer the function to be scaled
903        /// \param scale the multiplicative scale factor
904        c2_scaled_function_p(const c2_function<float_type> &outer, float_type scale) : 
905                c2_function<float_type>(), func(outer), yscale(scale) { }
906       
907        /// \brief set a new scale factor
908        /// \param scale the new factor
909        void reset(float_type scale) { yscale=scale; }
910       
911        /// \copydoc c2_function::value_with_derivatives
912        ///
913        /// provide our own value_with_derivatives which bypasses the combiner for quicker operation
914        virtual float_type value_with_derivatives(float_type x, float_type *yprime, float_type *yprime2) const throw (c2_exception) 
915    { 
916                float_type y=this->func->value_with_derivatives(x, yprime, yprime2); 
917                if(yprime) (*yprime)*=yscale; 
918                if(yprime2) (*yprime2)*=yscale; 
919                return y*yscale; 
920    }
921
922protected:
923    c2_scaled_function_p<float_type>() : func() {} // hide default constructor, since its use is almost always an error.
924        /// \brief the scaling factor for the function
925        const c2_const_ptr<float_type> func;
926        float_type yscale;
927};
928
929/// \brief A container into which any other c2_function can be dropped.
930/// \ingroup containers
931/// It allows a function to be pre-evaluated at a point, and used at multiple places in an expression
932/// efficiently. If it is re-evaluated at the previous point, it returns the remembered values;
933/// otherwise, it re-evauates the function at the new point.
934///
935/// The factory function c2_factory::cached_function() creates *new c2_cached_function_p
936template <typename float_type=double> class c2_cached_function_p : public c2_function<float_type> {
937public:
938        /// \brief construct the container
939        ///
940        /// \param f the function to be cached
941        c2_cached_function_p(const c2_function<float_type> &f) : c2_function<float_type>(),
942                func(f), init(false)  {}
943        /// \copydoc c2_function::value_with_derivatives
944        ///
945        /// Checks to see if the function is being re-evaluated at the previous point, and
946        /// returns remembered values if so.
947        virtual float_type value_with_derivatives(float_type x, float_type *yprime, float_type *yprime2) const throw(c2_exception) 
948    {
949                if(!init || x != x0) {
950                        y=this->func->value_with_derivatives(x, &yp, &ypp);
951                        x0=x;
952                        init=true;
953                }
954                if(yprime) *yprime=yp;
955                if(yprime2) *yprime2=ypp;
956                return y; 
957        }
958
959protected:
960    c2_cached_function_p() : func() {} // hide default constructor, since its use is almost always an error.
961        const c2_const_ptr<float_type> func;
962        mutable bool init;
963        mutable float_type x0, y, yp, ypp;
964       
965};
966
967/// \brief Provides function composition (nesting)
968/// \ingroup arithmetic_functions
969/// This allows evaluation of \a f(g(x)) where \a f and \a g are c2_function objects.
970///
971/// This should always be constructed using \ref compose_operator "c2_function::operator()"
972template <typename float_type=double> class  c2_composed_function_p : public c2_binary_function<float_type> {
973public:
974       
975        /// \brief construct \a outer( \a inner (x))
976    /// \note See c2_binary_function for discussion of ownership.
977        /// \param outer the outer function
978        /// \param inner the inner function
979        c2_composed_function_p(const c2_function<float_type> &outer, const c2_function<float_type> &inner) : 
980                c2_binary_function<float_type>(combine, outer, inner) { this->set_domain(inner.xmin(), inner.xmax()); }
981        /// \brief Create a stub just for the combiner to avoid statics.
982        c2_composed_function_p() : c2_binary_function<float_type>(combine) {} 
983
984        /// \brief execute math necessary to do composition
985        static float_type combine(const c2_function<float_type> &left, const c2_function<float_type> &right, 
986                                                  float_type x, float_type *yprime, float_type *yprime2) throw(c2_exception)
987    {
988                float_type y0, y1;
989                if(yprime || yprime2) {
990                        float_type yp0, ypp0, yp1, ypp1;
991                        y0=right.value_with_derivatives(x, &yp0, &ypp0);
992                        y1=left.value_with_derivatives(y0, &yp1, &ypp1);
993                        if(yprime) *yprime=yp1*yp0;
994                        if(yprime2) *yprime2=ypp0*yp1+yp0*yp0*ypp1;
995                } else {
996                        y0=right(x);
997                        y1=left(y0);
998                }
999                return y1;
1000        }       
1001};
1002
1003/// \brief create a c2_function which is the sum of two other c2_function objects.
1004/// \ingroup arithmetic_functions
1005/// This should always be constructed using c2_function::operator+()
1006template <typename float_type=double> class c2_sum_p : public c2_binary_function<float_type> {
1007public: 
1008        /// \brief construct \a left + \a right
1009        /// \param left the left function
1010        /// \param right the right function
1011        c2_sum_p(const c2_function<float_type> &left, const c2_function<float_type> &right) : c2_binary_function<float_type>(combine, left, right) {}
1012        /// \brief Create a stub just for the combiner to avoid statics.
1013        c2_sum_p() : c2_binary_function<float_type>(combine) {} ; // create a stub just for the combiner to avoid statics
1014
1015        /// \brief execute math necessary to do addition
1016        static float_type combine(const c2_function<float_type> &left, const c2_function<float_type> &right, 
1017                                                  float_type x, float_type *yprime, float_type *yprime2) throw(c2_exception)
1018    {
1019                float_type y0, y1;
1020                if(yprime || yprime2) {
1021                        float_type yp0, ypp0, yp1, ypp1;
1022                        y0=left.value_with_derivatives(x, &yp0, &ypp0);
1023                        y1=right.value_with_derivatives(x, &yp1, &ypp1);
1024                        if(yprime) *yprime=yp0+yp1;
1025                        if(yprime2) *yprime2=ypp0+ypp1;
1026                } else {
1027                        y0=left(x);
1028                        y1=right(x);
1029                }
1030                return y0+y1;
1031        }
1032};
1033
1034
1035/// \brief create a c2_function which is the difference of two other c2_functions.
1036/// \ingroup arithmetic_functions
1037/// This should always be constructed using c2_function::operator-()
1038template <typename float_type=double> class c2_diff_p : public c2_binary_function<float_type> {
1039public: 
1040        /// \brief construct \a left - \a right
1041        /// \param left the left function
1042        /// \param right the right function
1043        c2_diff_p(const c2_function<float_type> &left, const c2_function<float_type> &right) : c2_binary_function<float_type>(combine, left, right) {}
1044        /// \brief Create a stub just for the combiner to avoid statics.
1045        c2_diff_p() : c2_binary_function<float_type>(combine) {} ; // create a stub just for the combiner to avoid statics
1046
1047        /// \brief execute math necessary to do subtraction
1048        static float_type combine(const c2_function<float_type> &left, const c2_function<float_type> &right, 
1049                                                          float_type x, float_type *yprime, float_type *yprime2) throw(c2_exception)
1050    {
1051                float_type y0, y1;
1052                if(yprime || yprime2) {
1053                        float_type yp0, ypp0, yp1, ypp1;
1054                        y0=left.value_with_derivatives(x, &yp0, &ypp0);
1055                        y1=right.value_with_derivatives(x, &yp1, &ypp1);
1056                        if(yprime) *yprime=yp0-yp1;
1057                        if(yprime2) *yprime2=ypp0-ypp1;
1058                } else {
1059                        y0=left(x);
1060                        y1=right(x);
1061                }
1062                return y0-y1;
1063        }
1064};
1065
1066
1067/// \brief create a c2_function which is the product of two other c2_functions.
1068/// \ingroup arithmetic_functions
1069/// This should always be constructed using c2_function::operator*()
1070template <typename float_type=double> class c2_product_p : public c2_binary_function<float_type> {
1071public: 
1072        /// \brief construct \a left * \a right
1073        /// \param left the left function
1074        /// \param right the right function
1075        c2_product_p(const c2_function<float_type> &left, const c2_function<float_type> &right) : c2_binary_function<float_type>(combine, left, right) {}
1076        /// \brief Create a stub just for the combiner to avoid statics.
1077        c2_product_p() : c2_binary_function<float_type>(combine) {} ; // create a stub just for the combiner to avoid statics
1078
1079        /// \brief execute math necessary to do multiplication
1080        static float_type combine(const c2_function<float_type> &left, const c2_function<float_type> &right, 
1081                                                           float_type x, float_type *yprime, float_type *yprime2)  throw(c2_exception)
1082    {
1083                float_type y0, y1;
1084                if(yprime || yprime2) {
1085                        float_type yp0, ypp0, yp1, ypp1;
1086                        y0=left.value_with_derivatives(x, &yp0, &ypp0);
1087                        y1=right.value_with_derivatives(x, &yp1, &ypp1);
1088                        if(yprime) *yprime=y1*yp0+y0*yp1;
1089                        if(yprime2) *yprime2=ypp0*y1+2.0*yp0*yp1+ypp1*y0;
1090                } else {
1091                        y0=left(x);
1092                        y1=right(x);
1093                }
1094                return y0*y1;
1095        }
1096};
1097
1098
1099/// \brief create a c2_function which is the ratio of two other c2_functions.
1100/// \ingroup arithmetic_functions
1101/// This should always be constructed using c2_function::operator/()
1102template <typename float_type=double> class c2_ratio_p : public c2_binary_function<float_type> {
1103public: 
1104        /// \brief construct \a left / \a right
1105        /// \param left the left function
1106        /// \param right the right function
1107        c2_ratio_p(const c2_function<float_type> &left, const c2_function<float_type> &right) : c2_binary_function<float_type>(combine, left, right) {}
1108        /// \brief Create a stub just for the combiner to avoid statics.
1109        c2_ratio_p() : c2_binary_function<float_type>(combine) {} ; // create a stub just for the combiner to avoid statics
1110       
1111        /// \brief execute math necessary to do division
1112        static float_type combine(const c2_function<float_type> &left, const c2_function<float_type> &right, 
1113                                                          float_type x, float_type *yprime, float_type *yprime2) throw(c2_exception)
1114    {
1115                float_type y0, y1;
1116                if(yprime || yprime2) {
1117                        float_type yp0, ypp0, yp1, ypp1;
1118                        y0=left.value_with_derivatives(x, &yp0, &ypp0);
1119                        y1=right.value_with_derivatives(x, &yp1, &ypp1);
1120                        if(yprime) *yprime=(yp0*y1-y0*yp1)/(y1*y1); // first deriv of ratio
1121                        if(yprime2) *yprime2=(y1*y1*ypp0+y0*(2*yp1*yp1-y1*ypp1)-2*y1*yp0*yp1)/(y1*y1*y1); 
1122                } else {
1123                        y0=left(x);
1124                        y1=right(x);
1125                }
1126                return y0/y1;
1127        }
1128
1129};
1130
1131/// \brief a c2_function which is constant
1132/// \ingroup parametric_functions
1133///
1134/// The factory function c2_factory::constant() creates *new c2_constant_p()
1135template <typename float_type> class c2_constant_p : public c2_function<float_type> {
1136public:
1137        c2_constant_p(float_type x) : c2_function<float_type>(), value(x) {}
1138        void reset(float_type val) { value=val; }
1139        virtual float_type value_with_derivatives(float_type x, float_type *yprime, float_type *yprime2) const throw(c2_exception) 
1140        { if(yprime) *yprime=0; if(yprime2) *yprime2=0; return value; }
1141       
1142private:
1143                float_type value;
1144};
1145
1146/// \brief a transformation of a coordinate, including an inverse
1147/// \ingroup transforms
1148template <typename float_type> class c2_transformation {
1149public:
1150        /// \brief initialize all our function pointers
1151        /// \param transformed true if this function is not the identity
1152        /// \param xin input X transform
1153        /// \param xinp input X transform derivative
1154        /// \param xinpp input X transform second derivative
1155        /// \param xout output X transform, which MUST be the inverse of \a xin
1156        c2_transformation(bool transformed,
1157                   float_type (*xin)(float_type), float_type (*xinp)(float_type), float_type (*xinpp)(float_type), float_type (*xout)(float_type)
1158           ) :
1159                        fTransformed(transformed), fHasStaticTransforms(true),
1160                        pIn(xin), pInPrime(xinp), pInDPrime(xinpp), pOut(xout) { }
1161
1162        /// \brief initialize all our function pointers so that only the (overridden) virtual functions can be called without an error
1163        /// \param transformed true if this function is nonlinear
1164        c2_transformation(bool transformed) :
1165                        fTransformed(transformed), fHasStaticTransforms(false),
1166                        pIn(report_error), pInPrime(report_error), pInDPrime(report_error), pOut(report_error) { }
1167        /// \brief the destructor
1168        virtual ~c2_transformation() { }
1169        /// \brief flag to indicate if this transform is not the identity
1170        const bool fTransformed;
1171        /// \brief flag to indicate if the static function pointers can be used for efficiency
1172        const bool fHasStaticTransforms;
1173
1174        /// \note the pointers to functions allow highly optimized access when static functions are available.
1175        /// They are only used inside value_with_derivatives(), which is assumed to be the most critical routine.
1176        /// \brief non-virtual pointer to input X transform
1177        float_type (* const pIn)(float_type);
1178        /// \brief non-virtual pointer to input X transform derivative
1179        float_type (* const pInPrime)(float_type);
1180        /// \brief non-virtual pointer to input X transform second derivative
1181        float_type (* const pInDPrime)(float_type);
1182        /// \brief non-virtual pointer to output X transform
1183        float_type (* const pOut)(float_type);
1184       
1185        /// \brief virtual input X transform
1186        virtual float_type fIn(float_type x) const { return pIn(x); }
1187        /// \brief virtual input X transform derivative
1188        virtual float_type fInPrime(float_type x) const { return pInPrime(x); }
1189        /// \brief virtual input X transform second derivative
1190        virtual float_type fInDPrime(float_type x) const { return pInDPrime(x); }
1191        /// \brief virtual output X transform
1192        virtual float_type fOut(float_type x) const { return pOut(x); }
1193
1194protected:
1195        /// \brief utility function for unimplemented conversion
1196        static float_type report_error(float_type x)  { throw c2_exception("use of improperly constructed axis transform"); return x; }
1197        /// \brief utility function f(x)=x useful in axis transforms
1198        static float_type ident(float_type x)  { return x; }
1199        /// \brief utility function f(x)=1 useful in axis transforms
1200        static float_type one(float_type)  { return 1; }
1201        /// \brief utility function f(x)=0 useful in axis transforms
1202        static float_type zero(float_type)  { return 0; }
1203        /// \brief utility function f(x)=1/x useful in axis transforms
1204        static float_type recip(float_type x)  { return 1.0/x; }
1205        /// \brief utility function f(x)=-1/x**2 useful in axis transforms
1206        static float_type recip_prime(float_type x)  { return -1/(x*x); }
1207        /// \brief utility function f(x)=2/x**3 useful in axis transforms
1208        static float_type recip_prime2(float_type x)  { return 2/(x*x*x); }
1209
1210};
1211
1212/// \brief the identity transform
1213/// \ingroup transforms
1214template <typename float_type> class c2_transformation_linear : public c2_transformation<float_type> {
1215public:
1216        /// \brief constructor
1217        c2_transformation_linear() : c2_transformation<float_type>(false, this->ident, this->one, this->zero, this->ident) { }
1218        /// \brief destructor
1219        ~c2_transformation_linear() { }
1220};
1221/// \brief log axis transform
1222/// \ingroup transforms
1223template <typename float_type> class c2_transformation_log : public c2_transformation<float_type> {
1224public:
1225        /// \brief constructor
1226        c2_transformation_log() : c2_transformation<float_type>(true, std::log, this->recip, this->recip_prime, std::exp) { }
1227        /// \brief destructor
1228        ~c2_transformation_log() { }
1229};
1230/// \brief reciprocal axis transform
1231/// \ingroup transforms
1232template <typename float_type> class c2_transformation_recip : public c2_transformation<float_type> {
1233public:
1234        /// \brief constructor
1235        c2_transformation_recip() : c2_transformation<float_type>(true, this->recip, this->recip_prime, this->recip_prime2, this->recip) { }
1236        /// \brief destructor
1237        ~c2_transformation_recip() { }
1238};
1239
1240/// \brief a transformation of a function in and out of a coordinate space, using 2 c2_transformations
1241///
1242/// This class is a container for two axis transforms, but also provides the critical evaluate()
1243/// function which converts a result in internal coordinates (with derivatives) into the external representation
1244/// \ingroup transforms
1245template <typename float_type> 
1246        class c2_function_transformation {
1247public:
1248        /// \brief construct this from two c2_transformation instances
1249        /// \param xx the X axis transform
1250        /// \param yy the Y axis transform 
1251        c2_function_transformation(
1252                const c2_transformation<float_type> &xx, const c2_transformation<float_type> &yy) :
1253                isIdentity(!(xx.fTransformed || yy.fTransformed)), X(xx), Y(yy) { }
1254        /// \brief destructor
1255        virtual ~c2_function_transformation() { delete &X; delete &Y; }
1256        /// \brief evaluate the transformation from internal coordinates to external coordinates
1257        /// \param xraw the value of \a x in external cordinates at which the transform is taking place
1258        /// \param y the value of the function in internal coordinates
1259        /// \param yp0 the derivative in internal coordinates
1260        /// \param ypp0 the second derivative in internal coordinates
1261        /// \param [out] yprime pointer to the derivative, or NULL, in external coordinates
1262        /// \param [out] yprime2 pointer to the second derivative, or NULL, in external coordinates
1263        /// \return the value of the function in external coordinates
1264        virtual float_type evaluate(float_type xraw, 
1265                float_type y, float_type yp0, float_type ypp0,
1266                float_type *yprime, float_type *yprime2) const;
1267        /// \brief flag indicating of the transform is the identity, and can be skipped for efficiency
1268        const bool isIdentity;
1269        /// \brief the X axis transform
1270        const c2_transformation<float_type> &X;
1271        /// \brief the Y axis transform
1272        const c2_transformation<float_type> &Y;
1273};
1274
1275/// \brief a transformation of a function in and out of lin-lin space
1276///
1277/// \ingroup transforms
1278template <typename float_type> class c2_lin_lin_function_transformation : 
1279        public c2_function_transformation<float_type> {
1280public:
1281        c2_lin_lin_function_transformation() : 
1282                c2_function_transformation<float_type>(
1283                        *new c2_transformation_linear<float_type>, 
1284                        *new c2_transformation_linear<float_type>
1285                ) { }
1286        virtual ~c2_lin_lin_function_transformation() { }
1287};
1288
1289/// \brief a transformation of a function in and out of log-log space
1290///
1291/// \ingroup transforms
1292template <typename float_type> class c2_log_log_function_transformation : 
1293        public c2_function_transformation<float_type> {
1294public:
1295        c2_log_log_function_transformation() : 
1296                c2_function_transformation<float_type>(
1297                        *new c2_transformation_log<float_type>, 
1298                        *new c2_transformation_log<float_type>
1299                ) { }
1300        virtual ~c2_log_log_function_transformation() { }
1301};
1302
1303/// \brief a transformation of a function in and out of lin-log space
1304///
1305/// \ingroup transforms
1306template <typename float_type> class c2_lin_log_function_transformation : 
1307        public c2_function_transformation<float_type> {
1308public:
1309        c2_lin_log_function_transformation() : 
1310                c2_function_transformation<float_type>(
1311                        *new c2_transformation_linear<float_type>, 
1312                        *new c2_transformation_log<float_type>
1313                ) { }
1314        virtual ~c2_lin_log_function_transformation() { }
1315};
1316
1317/// \brief a transformation of a function in and out of log-lin space
1318///
1319/// \ingroup transforms
1320template <typename float_type> class c2_log_lin_function_transformation : 
1321        public c2_function_transformation<float_type> {
1322public:
1323        c2_log_lin_function_transformation() : 
1324                c2_function_transformation<float_type>(
1325                        *new c2_transformation_log<float_type>, 
1326                        *new c2_transformation_linear<float_type>
1327                ) { }
1328        virtual ~c2_log_lin_function_transformation() { }
1329};
1330
1331/// \brief a transformation of a function in and out of Arrhenuis (1/x vs. log(y)) space
1332///
1333/// \ingroup transforms
1334template <typename float_type> class c2_arrhenius_function_transformation : 
1335        public c2_function_transformation<float_type> {
1336public:
1337        c2_arrhenius_function_transformation() : 
1338                c2_function_transformation<float_type>(
1339                        *new c2_transformation_recip<float_type>, 
1340                        *new c2_transformation_log<float_type>
1341                ) { }
1342        virtual ~c2_arrhenius_function_transformation() { }
1343};
1344
1345/**
1346    \brief create a cubic spline interpolation of a set of (x,y) pairs
1347        \ingroup interpolators
1348    This is one of the main reasons for c2_function objects to exist.
1349
1350    It provides support for cubic spline interpolation of data provides from tables of \a x, \a y pairs.
1351    It supports automatic, transparent linearization of the data before storing in its tables (through
1352    subclasses such as
1353    log_lin_interpolating_function, lin_log_interpolating_function, and
1354    log_log_interpolating_function) to permit very high accuracy representations of data which have a suitable
1355    structure.  It provides utility functions LinearInterpolatingGrid() and LogLogInterpolatingGrid()
1356    to create grids for mapping other functions onto a arithmetic or geometric grid.
1357
1358    In its simplest form, an untransformed cubic spline of a data set, using natural boundary conditions
1359    (vanishing second derivative), is created as: \n
1360    \code
1361        c2_ptr<double> c2p;
1362        c2_factory<double> c2;
1363    std::vector<double> xvals(10), yvals(10);
1364    // < fill in xvals and yvals >
1365    c2p myfunc=c2.interpolating_function().load(xvals, yvals,true,0,true,0);
1366    // and it can be evaluated at a point for its value only by:
1367    double y=myfunc(x);
1368    // or it can be evaluated with its derivatives by
1369    double yprime, yprime2;
1370    double y=myfunc(x,&yprime, &yprime2);
1371    \endcode
1372       
1373        The factory function c2_factory::interpolating_function() creates *new interpolating_function_p()
1374*/
1375
1376template <typename float_type=double> class interpolating_function_p  : public c2_function<float_type> {
1377public:
1378    /// \brief an empty linear-linear cubic-spline interpolating_function_p
1379    ///
1380    /// lots to say here, but see Numerical Recipes for a discussion of cubic splines.
1381        ///
1382        interpolating_function_p() : c2_function<float_type>(), 
1383                fTransform(*new  c2_lin_lin_function_transformation<float_type>) { } 
1384
1385    /// \brief an empty cubic-spline interpolating_function_p with a specific transform
1386    ///
1387        interpolating_function_p(const c2_function_transformation<float_type> &transform) : c2_function<float_type>(), 
1388                fTransform(transform) { } 
1389
1390    /// \brief do the dirty work of constructing the spline from a function.
1391    /// \param x the list of abscissas.  Must be either strictly increasing or strictly decreasing.
1392        /// Strictly increasing is preferred, as less memory is used since a copy is not required for the sampling grid.
1393    /// \param f the list of function values.
1394    /// \param lowerSlopeNatural if true, set y''(first point)=0, otherwise compute it from \a lowerSope
1395    /// \param lowerSlope derivative of the function at the lower bound, used only if \a lowerSlopeNatural is false
1396    /// \param upperSlopeNatural if true, set y''(last point)=0, otherwise compute it from \a upperSope
1397    /// \param upperSlope derivative of the function at the upper bound, used only if \a upperSlopeNatural is false
1398        /// \param splined if true (default), use cubic spline, if false, use linear interpolation.
1399        /// \return the same interpolating function, filled
1400        interpolating_function_p<float_type> & load(const std::vector<float_type> &x, const std::vector<float_type> &f, 
1401                          bool lowerSlopeNatural, float_type lowerSlope, 
1402                          bool upperSlopeNatural, float_type upperSlope, bool splined=true
1403        ) throw(c2_exception);
1404
1405    /// \brief do the dirty work of constructing the spline from a function.
1406    /// \param data std::vector of std::pairs of x,y.  Will be sorted into x increasing order in place.
1407    /// \param lowerSlopeNatural if true, set y''(first point)=0, otherwise compute it from \a lowerSope
1408    /// \param lowerSlope derivative of the function at the lower bound, used only if \a lowerSlopeNatural is false
1409    /// \param upperSlopeNatural if true, set y''(last point)=0, otherwise compute it from \a upperSope
1410    /// \param upperSlope derivative of the function at the upper bound, used only if \a upperSlopeNatural is false
1411        /// \param splined if true (default), use cubic spline, if false, use linear interpolation.
1412        /// \return the same interpolating function, filled
1413        interpolating_function_p<float_type> & load_pairs(
1414                          std::vector<std::pair<float_type, float_type> > &data, 
1415                          bool lowerSlopeNatural, float_type lowerSlope, 
1416                          bool upperSlopeNatural, float_type upperSlope, bool splined=true
1417        ) throw(c2_exception);
1418
1419    /// \brief do the dirty work of constructing the spline from a function.
1420    /// \param func a function without any requirement of valid derivatives to sample into an interpolating function.
1421        /// Very probably a c2_classic_function.
1422    /// \param xmin the lower bound of the region to sample
1423    /// \param xmax the upper bound of the region to sample
1424        /// \param abs_tol the maximum absolute error permitted when linearly interpolating the points.
1425        /// the real error will be much smaller, since this uses cubic splines at the end.
1426        /// \param rel_tol the maximum relative error permitted when linearly interpolating the points.
1427        /// the real error will be much smaller, since this uses cubic splines at the end.
1428    /// \param lowerSlopeNatural if true, set y'(first point) from 3-point parabola, otherwise compute it from \a lowerSope
1429    /// \param lowerSlope derivative of the function at the lower bound, used only if \a lowerSlopeNatural is false
1430    /// \param upperSlopeNatural if true, set y'(last point) from 3-point parabola, otherwise compute it from \a upperSope
1431    /// \param upperSlope derivative of the function at the upper bound, used only if \a upperSlopeNatural is false
1432        /// \return the same interpolating function, filled
1433        /// \note If the interpolator being filled has a log vertical axis, put the desired relative error in
1434        /// \a abs_tol, and 0 in \a rel_tol since the absolute error on the log of a function is the relative error
1435        /// on the function itself.
1436        interpolating_function_p<float_type> &  sample_function(const c2_function<float_type> &func, 
1437                          float_type xmin, float_type xmax, float_type abs_tol, float_type rel_tol,
1438                          bool lowerSlopeNatural, float_type lowerSlope, 
1439                          bool upperSlopeNatural, float_type upperSlope
1440                          ) throw(c2_exception);
1441       
1442
1443        /// \brief initialize from a grid of points and a c2_function (un-normalized) to an
1444        /// interpolator which, when evaluated with a uniform random variate on [0,1] returns random numbers
1445        /// distributed as the input function.
1446        /// \see  \ref random_subsec "Arbitrary random generation"
1447        /// inverse_integrated_density starts with a probability density  std::vector, generates the integral,
1448        /// and generates an interpolating_function_p  of the inverse function which, when evaluated using a uniform random on [0,1] returns values
1449        /// with a density distribution equal to the input distribution
1450        /// If the data are passed in reverse order (large X first), the integral is carried out from the big end.
1451        /// \param bincenters the positions at which to sample the function \a binheights
1452        /// \param binheights a function which describes the density of the random number distribution to be produced.
1453        /// \return an initialized interpolator, which
1454        /// if evaluated randomly with a uniform variate on [0,1] produces numbers
1455        /// distributed according to \a binheights
1456        interpolating_function_p<float_type> & load_random_generator_function(
1457                const std::vector<float_type> &bincenters, const c2_function<float_type> &binheights)
1458                throw(c2_exception);
1459
1460        /// \brief initialize from a grid of points and an std::vector of probability densities (un-normalized) to an
1461        /// interpolator which, when evaluated with a uniform random variate on [0,1] returns random numbers
1462        /// distributed as the input histogram.
1463        /// \see  \ref random_subsec "Arbitrary random generation"
1464        /// inverse_integrated_density starts with a probability density  std::vector, generates the integral,
1465        /// and generates an interpolating_function_p  of the inverse function which, when evaluated using a uniform random on [0,1] returns values
1466        /// with a density distribution equal to the input distribution
1467        /// If the data are passed in reverse order (large X first), the integral is carried out from the big end.
1468        /// \param bins if \a bins .size()==\a binheights .size(), the centers of the bins.  \n
1469        /// if \a bins .size()==\a binheights .size()+1, the edges of the bins
1470        /// \param binheights a vector which describes the density of the random number distribution to be produced.
1471        /// Note density... the numbers in the bins are not counts, but counts/unit bin width.
1472        /// \return an initialized interpolator, which
1473        /// if evaluated randomly with a uniform variate on [0,1] produces numbers
1474        /// distributed according to \a binheights
1475        interpolating_function_p<float_type> & load_random_generator_bins(
1476                const std::vector<float_type> &bins, const std::vector<float_type> &binheights)
1477                throw(c2_exception);
1478       
1479        virtual float_type value_with_derivatives(float_type x, float_type *yprime, float_type *yprime2) const throw(c2_exception);
1480       
1481        /// \brief destructor
1482        virtual ~interpolating_function_p() { delete &fTransform; } 
1483       
1484        /// \brief create a new, empty interpolating function of this type (virtual constructor)
1485        virtual interpolating_function_p<float_type> &clone() const throw(c2_exception)
1486        {       return *new interpolating_function_p<float_type>(); }
1487       
1488    /// \brief retrieve copies of the x & y tables from which this was built
1489    ///
1490        /// This is often useful in the creation of new interpolating functions with transformed data.
1491        /// The vectors will have their sizes set correctly on return.
1492        /// \param [in, out] xvals the abscissas
1493        /// \param [in, out] yvals the ordinates
1494        void get_data(std::vector<float_type> &xvals, std::vector<float_type> &yvals) const throw() ;
1495       
1496    /// \brief enable extrapolation of the function below the tabulated data.
1497    ///
1498    /// This allows the interpolator to be extrapolated outside the bounds of the data,
1499    /// using whatever derivatives it already had at the lower bound.
1500    /// \param bound the abscissa to which the function should be extended.
1501        void set_lower_extrapolation(float_type bound);
1502    /// \brief enable extrapolation of the function above the tabulated data.
1503    ///
1504    /// This allows the interpolator to be extrapolated outside the bounds of the data,
1505    /// using whatever derivatives it already had at the upper bound.
1506    /// \param bound the abscissa to which the function should be extended.
1507        void set_upper_extrapolation(float_type bound);
1508       
1509        // these functions correctly combine the interpolating function with another interpolating function
1510        // preserving the X bounds and mapping functions of the host (left hand) function.
1511       
1512    /// \brief create a new interpolating_function_p  which is the \a source
1513    /// function applied to every point in the interpolating tables
1514    ///
1515    /// This carefully manages the derivative of the composed function at the two ends.
1516    /// \param source the function to apply
1517    /// \return a new interpolating_function_p  with the same mappings for x and y
1518        interpolating_function_p <float_type> & unary_operator(const c2_function<float_type> &source) const;
1519
1520    /// \brief create a new interpolating_function_p  which is the parent interpolating_function_p 
1521    /// combined with \a rhs using \a combiner at every point in the interpolating tables
1522    ///
1523    /// This carefully manages the derivative of the composed function at the two ends.
1524    /// \param rhs the function to apply
1525    /// \param combining_stub a function which defines which binary operation to use.
1526    /// \return a new interpolating_function_p  with the same mappings for x and y
1527        interpolating_function_p <float_type> & binary_operator(const c2_function<float_type> &rhs,
1528           const c2_binary_function<float_type> *combining_stub
1529           ) const;
1530        /// \brief produce a newly resampled interpolating_function_p  which is the specified sum.
1531    /// \param rhs the function to add, pointwise
1532    /// \return a new interpolating_function_p
1533    interpolating_function_p <float_type> & add_pointwise (const c2_function<float_type> &rhs) const { 
1534                return binary_operator(rhs, new c2_sum_p<float_type>()); }
1535        /// \brief produce a newly resampled interpolating_function_p  which is the specified difference.
1536    /// \param rhs the function to subtract, pointwise
1537    /// \return a new interpolating_function_p
1538        interpolating_function_p <float_type> & subtract_pointwise (const c2_function<float_type> &rhs) const {
1539                return binary_operator(rhs, new c2_diff_p<float_type>()); }
1540        /// \brief produce a newly resampled interpolating_function_p  which is the specified product.
1541    /// \param rhs the function to multiply, pointwise
1542    /// \return a new interpolating_function_p
1543        interpolating_function_p <float_type> & multiply_pointwise (const c2_function<float_type> &rhs) const { 
1544                return binary_operator(rhs, new c2_product_p<float_type>()); }
1545        /// \brief produce a newly resampled interpolating_function_p  which is the specified ratio.
1546    /// \param rhs the function to divide, pointwise
1547    /// \return a new interpolating_function_p
1548        interpolating_function_p <float_type> & divide_pointwise (const c2_function<float_type> &rhs) const { 
1549                return binary_operator(rhs, new c2_ratio_p<float_type>()); }
1550    /// \brief copy data from another interpolating function.  This only makes sense if the source
1551        /// function has the same transforms as the destination.
1552    /// \param rhs interpolating_function_p  to copy from
1553        void clone_data(const interpolating_function_p <float_type> &rhs) {
1554                Xraw=rhs.Xraw; X=rhs.X; F=rhs.F; y2=rhs.y2;
1555                set_sampling_grid_pointer(Xraw);
1556        }
1557
1558        const c2_function_transformation<float_type> &fTransform;
1559       
1560protected:   
1561    /// \brief create the spline coefficients
1562        void spline(
1563                          bool lowerSlopeNatural, float_type lowerSlope, 
1564                          bool upperSlopeNatural, float_type upperSlope
1565                          ) throw(c2_exception);
1566
1567        // This is for sorting the data. It must be static if it's going to be a class member.
1568        static bool comp_pair(std::pair<float_type,float_type> const &i, std::pair<float_type,float_type> const &j) {return i.first<j.first;}
1569
1570    std::vector<float_type> Xraw, X, F, y2;
1571        c2_const_ptr<float_type> sampler_function;
1572        bool xInverted;
1573    mutable size_t lastKLow;
1574};
1575
1576/// \brief A spline with X transformed into log space. 
1577/// \ingroup interpolators
1578/// Most useful for functions looking like y=log(x) or any other function with a huge X dynamic range,
1579/// and a slowly varying Y.
1580///
1581///     The factory function c2_factory::log_lin_interpolating_function() creates *new log_lin_interpolating_function_p()
1582template <typename float_type=double> class log_lin_interpolating_function_p : public interpolating_function_p <float_type> {
1583public:
1584    /// \brief an empty log-linear cubic-spline interpolating_function_p
1585    ///
1586        log_lin_interpolating_function_p() : interpolating_function_p<float_type>(*new c2_log_lin_function_transformation<float_type>)
1587                { }
1588        /// \brief create a new, empty interpolating function of this type (virtual constructor)
1589        virtual interpolating_function_p<float_type> &clone() const throw(c2_exception)
1590                {       return *new log_lin_interpolating_function_p<float_type>(); }
1591};
1592
1593
1594/// \brief A spline with Y transformed into log space. 
1595/// \ingroup interpolators
1596/// Most useful for functions looking like y=exp(x)
1597///
1598///     The factory function c2_factory::lin_log_interpolating_function() creates *new lin_log_interpolating_function_p()
1599template <typename float_type=double> class lin_log_interpolating_function_p : public interpolating_function_p <float_type> {
1600public:
1601    /// \brief an empty linear-log cubic-spline interpolating_function_p
1602    ///
1603        lin_log_interpolating_function_p() : interpolating_function_p<float_type>(*new c2_lin_log_function_transformation<float_type>)
1604                { } 
1605        /// \brief create a new, empty interpolating function of this type (virtual constructor)
1606        virtual interpolating_function_p<float_type> &clone() const throw(c2_exception)
1607                {       return *new lin_log_interpolating_function_p<float_type>(); }
1608};
1609
1610
1611/// \brief A spline with X and Y transformed into log space. 
1612/// \ingroup interpolators
1613/// Most useful for functions looking like y=x^n or any other function with a huge X and Y dynamic range.
1614///
1615///     The factory function c2_factory::log_log_interpolating_function() creates *new log_log_interpolating_function_p()
1616template <typename float_type=double> class log_log_interpolating_function_p : public interpolating_function_p <float_type> {
1617public: 
1618    /// \brief an empty log-log cubic-spline interpolating_function_p
1619    ///
1620        log_log_interpolating_function_p() : interpolating_function_p<float_type>(*new c2_log_log_function_transformation<float_type>)
1621                { } 
1622        /// \brief create a new, empty interpolating function of this type (virtual constructor)
1623        virtual interpolating_function_p<float_type> &clone() const throw(c2_exception)
1624        {       return *new log_log_interpolating_function_p<float_type>(); }
1625};
1626
1627
1628/// \brief A spline with X in reciprocal space and Y transformed in log space. 
1629/// \ingroup interpolators
1630/// Most useful for thermodynamic types of data where Y is roughly A*exp(-B/x).
1631/// Typical examples are reaction rate data, and thermistor calibration data.
1632///
1633///     The factory function c2_factory::arrhenius_interpolating_function() creates *new arrhenius_interpolating_function_p()
1634template <typename float_type=double> class arrhenius_interpolating_function_p : public interpolating_function_p <float_type> {
1635public:
1636    /// \brief an empty arrhenius cubic-spline interpolating_function_p
1637    ///
1638        arrhenius_interpolating_function_p() : interpolating_function_p<float_type>(*new c2_arrhenius_function_transformation<float_type>)
1639                { } 
1640        /// \brief create a new, empty interpolating function of this type (virtual constructor)
1641        virtual interpolating_function_p<float_type> &clone() const throw(c2_exception)
1642        {       return *new arrhenius_interpolating_function_p<float_type>(); } 
1643};
1644
1645/// \brief compute sin(x) with its derivatives.
1646/// \ingroup math_functions
1647///
1648/// The factory function c2_factory::sin() creates *new c2_sin_p
1649template <typename float_type=double> class c2_sin_p : public c2_function<float_type> {
1650public:
1651        /// \brief constructor.
1652        c2_sin_p() : c2_function<float_type>() {}
1653       
1654        virtual float_type value_with_derivatives(float_type x, float_type *yprime, float_type *yprime2) const throw(c2_exception)
1655        { float_type q=std::sin(x); if(yprime) *yprime=std::cos(x); if(yprime2) *yprime2=-q; return q; }       
1656   
1657    /// \brief return a grid dynamically, suitable for use with trig functions with period 2*pi
1658    /// \param xmin the lower bound for the grid
1659    /// \param xmax upper bound for the grid
1660    /// \param [in, out] grid the sampling grid.
1661        virtual void get_sampling_grid(float_type xmin, float_type xmax,  std::vector<float_type> &grid) const; 
1662};
1663
1664/// \brief compute cos(x) with its derivatives.
1665/// \ingroup math_functions
1666///
1667/// The factory function c2_factory::cos() creates *new c2_cos_p
1668template <typename float_type=double> class c2_cos_p : public c2_sin_p<float_type> {
1669public:
1670        /// \brief constructor.
1671        c2_cos_p() : c2_sin_p<float_type>() {}
1672       
1673        virtual float_type value_with_derivatives(float_type x, float_type *yprime, float_type *yprime2) const throw(c2_exception)
1674        { float_type q=std::cos(x); if(yprime) *yprime=-std::sin(x); if(yprime2) *yprime2=-q; return q; }       
1675};
1676
1677/// \brief compute tan(x) with its derivatives.
1678/// \ingroup math_functions
1679///
1680/// The factory function c2_factory::tan() creates *new c2_tan_p
1681template <typename float_type=double> class c2_tan_p : public c2_function<float_type> {
1682public:
1683        /// \brief constructor.
1684        c2_tan_p() : c2_function<float_type>() {}
1685       
1686        virtual float_type value_with_derivatives(float_type x, float_type *yprime, float_type *yprime2) const throw(c2_exception)
1687        {
1688                float_type c=std::cos(x), s=std::sin(x);
1689                float_type t=s/c;
1690                float_type yp=1/(c*c);
1691                if(yprime) *yprime=yp; if(yprime2) *yprime2=2*t*yp; 
1692                return t; 
1693        }       
1694};
1695
1696/// \brief compute log(x) with its derivatives.
1697/// \ingroup math_functions
1698///
1699/// The factory function c2_factory::log() creates *new c2_log_p
1700template <typename float_type=double> class c2_log_p : public c2_function<float_type> {
1701public:
1702        /// \brief constructor.
1703        c2_log_p() : c2_function<float_type>() {}
1704
1705        virtual float_type value_with_derivatives(float_type x, float_type *yprime, float_type *yprime2) const throw(c2_exception)
1706        { if(yprime) *yprime=1.0/x; if(yprime2) *yprime2=-1.0/(x*x); return std::log(x); }     
1707};
1708
1709/// \brief compute exp(x) with its derivatives.
1710/// \ingroup math_functions
1711///
1712/// The factory function c2_factory::exp() creates *new c2_exp_p
1713template <typename float_type=double>  class c2_exp_p : public c2_function<float_type> {
1714public:
1715        /// \brief constructor.
1716        c2_exp_p() : c2_function<float_type>() {}
1717
1718        virtual float_type value_with_derivatives(float_type x, float_type *yprime, float_type *yprime2) const throw(c2_exception)
1719        { float_type q=std::exp(x); if(yprime) *yprime=q; if(yprime2) *yprime2=q; return q; }
1720};
1721
1722/// \brief compute sqrt(x) with its derivatives.
1723/// \ingroup math_functions
1724///
1725/// The factory function c2_factory::sqrt() creates *new c2_sqrt_p()
1726template <typename float_type=double> class c2_sqrt_p : public c2_function<float_type> {
1727public:
1728        /// \brief constructor.
1729        c2_sqrt_p() : c2_function<float_type>() {}
1730       
1731        virtual float_type value_with_derivatives(float_type x, float_type *yprime, float_type *yprime2) const throw(c2_exception)
1732        { float_type q=std::sqrt(x); if(yprime) *yprime=0.5/q; if(yprime2) *yprime2=-0.25/(x*q); return q; }
1733};
1734
1735/// \brief compute scale/x with its derivatives.
1736/// \ingroup parametric_functions
1737///
1738/// The factory function c2_factory::recip() creates *new c2_recip_p
1739template <typename float_type=double> class c2_recip_p : public c2_function<float_type> {
1740public:
1741        /// \brief constructor.
1742        c2_recip_p(float_type scale) : c2_function<float_type>(), rscale(scale) {}
1743       
1744        virtual float_type value_with_derivatives(float_type x, float_type *yprime, float_type *yprime2) const throw(c2_exception)
1745        { 
1746                float_type q=1.0/x; 
1747                float_type y=rscale*q;
1748                if(yprime) *yprime=-y*q; 
1749                if(yprime2) *yprime2=2*y*q*q; 
1750                return y; 
1751        }
1752        /// \brief reset the scale factor
1753        /// \param scale the new numerator
1754        void reset(float_type scale) { rscale=scale; } 
1755private:
1756        float_type rscale;
1757};
1758
1759/// \brief compute x with its derivatives.
1760/// \ingroup math_functions
1761///
1762/// The factory function c2_factory::identity() creates *new c2_identity_p
1763template <typename float_type=double> class c2_identity_p : public c2_function<float_type> {
1764public:
1765        /// \brief constructor.
1766        c2_identity_p() : c2_function<float_type>() {}
1767       
1768        virtual float_type value_with_derivatives(float_type x, float_type *yprime, float_type *yprime2) const throw(c2_exception)
1769        { if(yprime) *yprime=1.0; if(yprime2) *yprime2=0; return x; }
1770};
1771
1772/**
1773 \brief create a linear mapping of another function
1774 \ingroup parametric_functions
1775 for example, given a c2_function \a f
1776 \code
1777 c2_function<double> &F=c2_linear<double>(1.2, 2.0, 3.0)(f);
1778 \endcode
1779 produces a new c2_function F=2.0+3.0*(\a f - 1.2)
1780 
1781 The factory function c2_factory::linear() creates *new c2_linear_p
1782*/
1783template <typename float_type=double> class c2_linear_p : public c2_function<float_type> {
1784public:
1785    /// \brief Construct the operator f=y0 + slope * (x-x0)
1786        /// \param x0 the x offset
1787    /// \param y0 the y-intercept i.e. f(x0)
1788    /// \param slope the slope of the mapping
1789        c2_linear_p(float_type x0, float_type y0, float_type slope) : 
1790                c2_function<float_type>(), xint(x0), intercept(y0), m(slope) {}
1791    /// \brief Change the slope and intercepts after construction.
1792        /// \param x0 the x offset
1793    /// \param y0 the y-intercept
1794    /// \param slope the slope of the mapping
1795        void reset(float_type x0, float_type y0, float_type slope) { xint=x0; intercept=y0; m=slope; } 
1796        virtual float_type value_with_derivatives(float_type x, float_type *yprime, float_type *yprime2) const throw(c2_exception)
1797        { if(yprime) *yprime=m; if(yprime2) *yprime2=0; return m*(x-xint)+intercept; }
1798       
1799private:
1800                float_type xint, intercept, m;
1801protected:
1802                c2_linear_p() {} // do not allow naked construction... it is usually an accident.
1803};
1804
1805/**
1806\brief create a quadratic mapping of another function
1807 \ingroup parametric_functions
1808 for example, given a c2_function \a f
1809 \code
1810 c2_function<double> &F=c2_quadratic<double>(1.2, 2.0, 3.0, 4.0)(f);
1811 \endcode
1812 produces a new c2_function F=2.0 + 3.0*(f-1.2) + 4.0*(f-1.2)^2
1813
1814 note that the parameters are overdetermined, but allows the flexibility of two different representations
1815
1816 The factory function c2_factory::quadratic() creates *new c2_quadratic_p
1817 */
1818template <typename float_type=double> class c2_quadratic_p : public c2_function<float_type> {
1819public:
1820    /// \brief Construct the operator
1821    /// \param x0 the center around which the powers are computed
1822    /// \param y0 the value of the function at \a x = \a x0
1823    /// \param xcoef the scale on the (\a x - \a x0) term
1824    /// \param x2coef the scale on the (\a x - \a x0)^2 term
1825        c2_quadratic_p(float_type x0, float_type y0, float_type xcoef, float_type x2coef) : 
1826                c2_function<float_type>(), intercept(y0), center(x0), a(x2coef), b(xcoef) {}
1827    /// \brief Modify the coefficients after construction
1828    /// \param x0 the new center around which the powers are computed
1829    /// \param y0 the new value of the function at \a x = \a x0
1830    /// \param xcoef the new scale on the (\a x - \a x0) term
1831    /// \param x2coef the new scale on the (\a x - \a x0)^2 term   
1832        void reset(float_type x0, float_type y0, float_type xcoef, float_type x2coef) { intercept=y0; center=x0; a=x2coef; b=xcoef; } 
1833        virtual float_type value_with_derivatives(float_type x, float_type *yprime, float_type *yprime2) const throw(c2_exception)
1834        { float_type dx=x-center; if(yprime) *yprime=2*a*dx+b; if(yprime2) *yprime2=2*a; return a*dx*dx+b*dx+intercept; }
1835       
1836private:
1837                float_type intercept, center, a, b;
1838protected:
1839                c2_quadratic_p() {} // do not allow naked construction... it is usually an accident.
1840};
1841
1842/**
1843\brief create a power law mapping of another function
1844 \ingroup parametric_functions
1845 for example, given a c2_function \a f
1846 \code
1847 c2_power_law_p<double> PLaw(1.2, 2.5);
1848 c2_composed_function_p<double> &F=PLaw(f);
1849 \endcode
1850 produces a new c2_function F=1.2 * f^2.5
1851 
1852 The factory function c2_factory::power_law() creates *new c2_power_law_p
1853 */
1854template <typename float_type=double> class c2_power_law_p : public c2_function<float_type> {
1855public:
1856    /// \brief Construct the operator
1857    /// \param scale the multipler
1858    /// \param power the exponent
1859        c2_power_law_p(float_type scale, float_type power) :
1860                c2_function<float_type>(), a(scale), b(power) {}
1861    /// \brief Modify the mapping after construction
1862    /// \param scale the new multipler
1863    /// \param power the new exponent
1864        void reset(float_type scale, float_type power) { a=scale; b=power; }
1865        virtual float_type value_with_derivatives(float_type x, float_type *yprime, float_type *yprime2) const throw(c2_exception)
1866        { float_type q=a*std::pow(x,b-2); if(yprime) *yprime=b*q*x; if(yprime2) *yprime2=b*(b-1)*q; return q*x*x; }
1867       
1868private:
1869                float_type a, b;
1870protected:
1871                c2_power_law_p() {} // do not allow naked construction... it is usually an accident.
1872};
1873
1874/**
1875\brief create the formal inverse function of another function
1876 \ingroup containers
1877 for example, given a c2_function \a f
1878 \code
1879 c2_inverse_function<double> inv(f);
1880 a=f(x);
1881 x1=inv(a);
1882 \endcode
1883 will return x1=x to machine precision.  The important part of this
1884 is that the resulting function is a first-class c2_function, so it knows its
1885 derivatives, too, unlike the case of a simple root-finding inverse.  This means
1886 it can be integrated (for example) quite efficiently.
1887
1888 \see \ref combined_inversion_hinting_sampling
1889
1890 The factory function c2_factory::inverse_function() creates *new c2_inverse_function_p
1891*/
1892template <typename float_type=double> class c2_inverse_function_p : public c2_function<float_type> {
1893public:
1894    /// \brief Construct the operator
1895    /// \param source the function to be inverted
1896        c2_inverse_function_p(const c2_function<float_type> &source); 
1897    virtual float_type value_with_derivatives(float_type x, float_type *yprime, float_type *yprime2) const throw(c2_exception);
1898   
1899    /// \brief give the function a hint as to where to look for its inverse
1900    /// \param hint the likely value of the inverse, which defaults to whatever the evaluation returned.
1901    void set_start_hint(float_type hint) const { start_hint=hint; }
1902   
1903    /// \brief get the starting hint. 
1904    ///
1905    /// This is virtual so if there is a better way, this can be easily overridden.
1906    ///  It is used in value_with_derivatives() to guess where to start the root finder.
1907    /// \param x the abscissa for which an estimate is needed
1908    virtual float_type get_start_hint(float_type x) const 
1909                { return hinting_function.valid()? hinting_function(x) : start_hint; } 
1910
1911        /// \brief set or unset the approximate function used to start the root finder
1912        /// \anchor set_hinting_function_discussion
1913        /// A hinting function is mostly useful if the evaluation of this inverse is
1914        /// going to be carried out in very non-local order, so the root finder has to start over
1915        /// for each step.  If most evaluations are going to be made in fairly localized clusters (scanning
1916        /// through the function, for example), the default mechanism used (which just remembers the last point)
1917        /// is almost certainly faster.
1918        ///
1919        /// Typically, the hinting function is likely to be set up by creating the inverse function,
1920        /// and then adaptively sampling an interpolating function from it, and then using the result
1921        /// to hint it.  Another way, if the parent function is already an interpolating function, is just to create
1922        /// a version of the parent with the x & y coordinates reversed.
1923        ///
1924        /// \see \ref combined_inversion_hinting_sampling
1925        ///
1926        /// \param hint_func the function that is an approximate inverse of the parent of this inverse_function
1927        void set_hinting_function(const c2_function<float_type> *hint_func) 
1928                { hinting_function.set_function(hint_func); }
1929    /// \brief set the hinting function from a pointer.
1930        ///
1931        /// See \ref set_hinting_function_discussion "discussion"
1932        /// \param hint_func the container holding the function
1933        void set_hinting_function(const c2_const_ptr<float_type> hint_func) 
1934                { hinting_function=hint_func; }
1935       
1936protected:
1937        c2_inverse_function_p() {} // do not allow naked construction... it is usually an accident.
1938        mutable float_type start_hint;
1939        const c2_const_ptr<float_type> func;
1940        c2_const_ptr<float_type> hinting_function;
1941};
1942
1943/**
1944  \brief
1945    An interpolating_function_p  which is the cumulative integral of a histogram.
1946        \ingroup interpolators
1947    Note than binedges should be one element longer than binheights, since the lower & upper edges are specified.
1948    Note that this is a malformed spline, since the second derivatives are all zero, so it has less continuity.
1949    Also, note that the bin edges can be given in backwards order to generate the
1950    reversed accumulation (starting at the high end)
1951*/
1952
1953template <typename float_type=double>  class accumulated_histogram : public interpolating_function_p <float_type> {
1954public:
1955    /// \brief Construct the integrated histogram
1956    /// \param binedges the edges of the bins in \a binheights.  It should have one more element than \a binheights
1957    /// \param binheights the number of counts in each bin.
1958    /// \param normalize if true, normalize integral to 1
1959    /// \param inverse_function if true, drop zero channels, and return inverse function for random generation
1960    /// \param drop_zeros eliminate null bins before integrating, so integral is strictly monotonic.
1961        accumulated_histogram(const std::vector<float_type>binedges, const std::vector<float_type> binheights,
1962                                                 bool normalize=false, bool inverse_function=false, bool drop_zeros=true);
1963       
1964};
1965
1966/**
1967        \anchor inverse_integrated_density_bins
1968        \brief construct from a grid of points and an std::vector of probability densities (un-normalized)
1969        \see  \ref random_subsec "Arbitrary random generation"
1970        \ingroup interpolators
1971         inverse_integrated_density starts with a probability density  std::vector, generates the integral,
1972         and generates an interpolating_function_p  of the inverse function which, when evaluated using a uniform random on [0,1] returns values
1973         with a density distribution equal to the input distribution
1974         If the data are passed in reverse order (large X first), the integral is carried out from the big end.
1975         
1976        \param bins if \a bins .size()==\a binheights .size(), the centers of the bins.  \n
1977        if \a bins .size()==\a binheights .size()+1, the edges of the bins
1978        \param binheights a vector which describes the density of the random number distribution to be produced.
1979        Note density... the numbers in the bins are not counts, but counts/unit bin width.
1980        \return an interpolating_function_p  of the type requested in the template which,
1981        if evaluated randomly with a uniform variate on [0,1] produces numbers
1982        distributed according to \a binheights
1983*/
1984
1985template <typename float_type, typename Final> 
1986interpolating_function_p<float_type> & inverse_integrated_density_bins(
1987                const std::vector<float_type> &bins, const std::vector<float_type> &binheights) 
1988                throw(c2_exception);
1989
1990/**
1991\anchor inverse_integrated_density_function
1992        \brief construct from a grid of points and a c2_function of probability densities (un-normalized)
1993        \see  \ref random_subsec "Arbitrary random generation"
1994        \ingroup interpolators
1995 inverse_integrated_density starts with a probability density  std::vector, generates the integral,
1996 and generates an interpolating_function_p  of the inverse function which, when evaluated using a uniform random on [0,1] returns values
1997 with a density distribution equal to the input distribution
1998 If the data are passed in reverse order (large X first), the integral is carried out from the big end.
1999 
2000        \param bincenters the centers of the bins.
2001        \param binheights a c2_function which describes the density of the random number distribution to be produced.
2002        \return an interpolating_function_p  of the type requested in the template which,
2003        if evaluated randomly with a uniform variate on [0,1] produces numbers
2004        distributed according to \a binheights
2005 */
2006template <typename float_type, typename Final> 
2007interpolating_function_p<float_type>  & inverse_integrated_density_function(
2008                const std::vector<float_type> &bincenters, const c2_function<float_type> &binheights)
2009                throw(c2_exception);
2010
2011/// \brief create a c2_function which smoothly connects two other c2_functions.
2012/// \ingroup parametric_functions
2013/// This takes two points and generates a polynomial which matches two c2_function arguments
2014/// at those two points, with two derivatives at each point, and an arbitrary value at the center of the
2015/// region.  It is useful for splicing together functions over rough spots (0/0, for example).
2016///
2017/// If \a auto_center is true, the value at the midpoint is computed so that the resulting polynomial is
2018/// of order 5.  If \a auto_center is false, the value \a y1 is used at the midpoint, resulting in a
2019/// polynomial of order 6.
2020///
2021/// This is usually used in conjunction with c2_piecewise_function_p to assemble an apparently seamless
2022/// function from a series of segments.
2023/// \see \ref piecewise_applications_subsec "Sample Applications" and \ref c2_function::adaptively_sample() "Adaptive sampling"
2024///
2025/// The factory function c2_factory::connector_function() creates *new c2_connector_function_p
2026template <typename float_type=double> class c2_connector_function_p : public c2_function<float_type> {
2027public: 
2028        /// \brief construct the container from two functions
2029        /// \param x0 the point at which to match \a f1 and its derivatives
2030        /// \param f0 the function on the left side to be connected
2031        /// \param x2 the point at which to match \a f2 and its derivatives
2032        /// \param f2 the function on the right side to be connected
2033        /// \param auto_center if true, no midpoint value is specified.  If false, match the value \a y1 at the midpoint
2034        /// \param y1 the value to match at the midpoint, if \a auto_center is false
2035        /// \return a c2_function with domain (\a x0,\a x2) which smoothly connects \a f0(x0) and \a f2(x2)
2036        c2_connector_function_p(float_type x0, const c2_function<float_type> &f0, float_type x2, const c2_function<float_type> &f2, 
2037                        bool auto_center, float_type y1);
2038        /// \brief construct the container from numerical values
2039        /// \param x0 the position of the left edge
2040        /// \param y0 the function derivative on the left boundary
2041        /// \param yp0 the function second derivative on the left boundary
2042        /// \param ypp0 the function value on the left boundary
2043        /// \param x2 the position of the right edge
2044        /// \param y2 the function derivative on the right boundary
2045        /// \param yp2 the function second derivative on the right boundary
2046        /// \param ypp2 the function value on the right boundary
2047        /// \param auto_center if true, no midpoint value is specified.  If false, match the value \a y1 at the midpoint
2048        /// \param y1 the value to match at the midpoint, if \a auto_center is false
2049        /// \return a c2_function with domain (\a x0,\a x2) which smoothly connects the points described
2050        /// \anchor c2_connector_raw_init_docs
2051        c2_connector_function_p(
2052                float_type x0, float_type y0, float_type yp0, float_type ypp0, 
2053                float_type x2, float_type y2, float_type yp2, float_type ypp2, 
2054                bool auto_center, float_type y1);
2055        /// \brief construct the container from c2_fblock<float_type> objects
2056        /// \param fb0 the left edge
2057        /// \param fb2 the right edge
2058        /// \param auto_center if true, no midpoint value is specified.  If false, match the value \a y1 at the midpoint
2059        /// \param y1 the value to match at the midpoint, if \a auto_center is false
2060        /// \return a c2_function with domain (\a fb0.x,\a fb2.x) which smoothly connects \a fb0 and \a fb2
2061        c2_connector_function_p(
2062                const c2_fblock<float_type> &fb0, 
2063                const c2_fblock<float_type> &fb2, 
2064                bool auto_center, float_type y1);
2065
2066        /// \brief destructor
2067        virtual ~c2_connector_function_p();
2068        virtual float_type value_with_derivatives(float_type x, float_type *yprime, float_type *yprime2) const throw (c2_exception);
2069protected:
2070        /// \brief fill container numerically
2071        void init(
2072                const c2_fblock<float_type> &fb0, 
2073                const c2_fblock<float_type> &fb2, 
2074                bool auto_center, float_type y1);
2075
2076        float_type fhinv, fy1, fa, fb, fc, fd, fe, ff;
2077};
2078
2079/// \brief create a c2_function which is a piecewise assembly of other c2_functions.
2080/// \ingroup containers
2081/// The functions must have increasing, non-overlapping domains.  Any empty space
2082/// between functions will be filled with a linear interpolation.
2083///
2084/// \note If you want a smooth connection, instead of the default linear interpolation,
2085/// create a c2_connector_function_p to bridge the gap.  The linear interpolation is intended
2086/// to be a barely intelligent bridge, and may never get used by anyone.
2087///
2088/// \note The creation of the container results in the creation of an explicit sampling grid. 
2089/// If this is used with functions with a large domain, or which generate very dense sampling grids,
2090/// it could eat a lot of memory.  Do not abuse this by using functions which can generate gigantic grids.
2091///
2092/// \see \ref piecewise_applications_subsec "Sample Applications" \n
2093/// c2_plugin_function_p page \n
2094/// c2_connector_function_p page \n
2095/// \ref c2_function::adaptively_sample() "Adaptive sampling"
2096///
2097/// The factory function c2_factory::piecewise_function() creates *new c2_piecewise_function_p
2098template <typename float_type=double> class c2_piecewise_function_p : public c2_function<float_type> {
2099public: 
2100        /// \brief construct the container
2101        c2_piecewise_function_p();
2102        /// \brief destructor
2103        virtual ~c2_piecewise_function_p();
2104        virtual float_type value_with_derivatives(float_type x, float_type *yprime, float_type *yprime2) const throw (c2_exception);
2105        /// \brief append a new function to the sequence
2106        ///
2107        /// This takes a c2_function, and appends it onto the end of the piecewise collection.
2108        /// The domain of the function (which MUST be set) specifies the place it will be used in
2109        /// the final function.  If the domain exactly abuts the domain of the previous function, it
2110        /// will be directly attached.  If there is a gap, the gap will be filled in by linear interpolation.
2111        /// \param func a c2_function with a defined domain to be appended to the collection
2112        void append_function(const c2_function<float_type> &func) throw (c2_exception);
2113protected:
2114        std::vector<c2_const_ptr<float_type> > functions;
2115        mutable int lastKLow;
2116};
2117
2118#include "c2_function.icc"
2119
2120#endif
Note: See TracBrowser for help on using the repository browser.