// -*- C++ -*-
// $Id: ParamToArgAdaptor.icc,v 1.2 2003/09/06 14:04:13 boudreau Exp $
#include "CLHEP/GenericFunctions/ParamToArgAdaptor.hh"
#include <assert.h>
#include <iostream>
#include <cfloat>

namespace Genfun {


//FUNCTION_OBJECT_IMP(ParamToArgAdaptor) Do it by hand here:

template <class F>
FunctionComposition ParamToArgAdaptor<F>::operator()(const AbsFunction & function) const
{                                            
  return AbsFunction::operator() (function); 
}     
                 
template <class F>                      
ParamToArgAdaptor<F> *ParamToArgAdaptor<F>::clone () const {       
  return (ParamToArgAdaptor<F> *) _clone();             
}
                                            
template <class F>                      
AbsFunction *ParamToArgAdaptor<F>::_clone () const {    
  return new ParamToArgAdaptor<F>(*this);                       
}



template<class F> 
ParamToArgAdaptor<F>::ParamToArgAdaptor(const F        &function,
				        ParamToArgAdaptor<F>::ScopedMethodPtr parameterFetchMethod):
  _scaleFactor("Sigma",  1.0,  0, 10),
  _function(function.clone()),
  _parameterFetchMethod(parameterFetchMethod)
{
  _parameterFetchMethod(*_function).setLowerLimit(-DBL_MAX);
  _parameterFetchMethod(*_function).setUpperLimit(+DBL_MAX);
}

template <class F>
ParamToArgAdaptor<F>::~ParamToArgAdaptor() {
  delete _function;
}

template <class F>
ParamToArgAdaptor<F>::ParamToArgAdaptor(const ParamToArgAdaptor & right):
  _scaleFactor(right._scaleFactor),
  _parameterFetchMethod(right._parameterFetchMethod),
  _function(right._function->clone())
{
  _parameterFetchMethod(*_function).setLowerLimit(-DBL_MAX);
  _parameterFetchMethod(*_function).setUpperLimit(+DBL_MAX);
}


template <class F>
double ParamToArgAdaptor<F>::operator ()(double x) const
{
  std::cerr
    << "Warning.  ParamToArgAdaptor called with scalar argument"
    << std::endl;
  assert(0);
  return 0;
}

template <class F>
Parameter & ParamToArgAdaptor<F>::scaleFactor() {
  return _scaleFactor;
}

template <class F>
const Parameter & ParamToArgAdaptor<F>::scaleFactor() const {
  return _scaleFactor;
}

template <class F>
unsigned int ParamToArgAdaptor<F>::dimensionality() const {
  return _function->dimensionality()+1;
}

template <class F> 
double ParamToArgAdaptor<F>::operator() (const Argument & a) const {
  if (dimensionality()!= a.dimension()) {
    std::cerr
      << "Warning: ParamToArgAdaptor function/argument dimension mismatch"
      <<  std::endl;
    assert(0);
    return 0;
  }
  int dMinus = a.dimension()-1;
  Argument aPrime(dMinus);
  for (int i=0;i<dMinus;i++) aPrime[i]=a[i];
  (_parameterFetchMethod(*_function)).setValue(_scaleFactor.getValue()*a[dMinus]);
  return (*_function)(a);
}

} // end of namespace Genfun 

