//#####################################################################
// Copyright 2013.
// This file is part of PhysBAM whose distribution is governed by the license contained in the accompanying file PHYSBAM_COPYRIGHT.txt.
//#####################################################################
#include <Core/Diff_Tools/Diff_Function_Test.h>
#include <Core/Diff_Tools/Diff_Test.h>
#include <Core/Random_Numbers/RANDOM_NUMBERS.h>
namespace PhysBAM{
template<class T> void
Diff_Function_Test(std::ostream& os,const ARRAY<T>& x,
    std::function<void(const ARRAY<T>& x,const ARRAY<T>& dx,
        T& e,ARRAY<T>& de,ARRAY<T>& dde_dx)> compute,
    const TEST_DIFF_OPTS<T>& opt,
    std::function<void(ARRAY<T>& x)> make_feasible)
{
    ARRAY<T> dx(x.m);
    opt.rand.Fill_Uniform(dx,-opt.eps,opt.eps);

    ARRAY<T> y(x+dx);
    if(make_feasible)
    {
        make_feasible(y);
        dx=y-x;
    }

    T e0=0,e1=0;
    ARRAY<T> de0(x.m),de1(x.m),dde0(x.m),dde1(x.m);
    compute(x,dx,e0,de0,dde0);
    compute(y,dx,e1,de1,dde1);

    if(opt.test_e)
        Diff_Test(os,opt.e_str,e0,x,de0,e1,y,de1);

    if(opt.test_de)
        Diff_Times_Test(os,opt.de_str,de0,dde0,x,de1,dde1,y);
}

template void Diff_Function_Test<double>(std::ostream&,ARRAY<double,int> const&,std::function<void (ARRAY<double,int> const&,ARRAY<double,int> const&,double&,ARRAY<double,int>&,ARRAY<double,int>&)>,TEST_DIFF_OPTS<double> const&,std::function<void (ARRAY<double,int>&)>);
template void Diff_Function_Test<float>(std::ostream&,ARRAY<float,int> const&,std::function<void (ARRAY<float,int> const&,ARRAY<float,int> const&,float&,ARRAY<float,int>&,ARRAY<float,int>&)>,TEST_DIFF_OPTS<float> const&,std::function<void (ARRAY<float,int>&)>);
}
