//#####################################################################
// Copyright 2015, Craig Schroeder.
// This file is part of PhysBAM whose distribution is governed by the license contained in the accompanying file PHYSBAM_COPYRIGHT.txt.
//#####################################################################
#ifndef __PARTICLE_GRID_WEIGHTS_SPLINE__
#define __PARTICLE_GRID_WEIGHTS_SPLINE__
#include <Hybrid_Methods/Iterators/PARTICLE_GRID_ITERATOR.h>
#include <Hybrid_Methods/Iterators/PARTICLE_GRID_WEIGHTS.h>
namespace PhysBAM{

template<class TV> class GRID;

template<class TV,int degree>
class PARTICLE_GRID_WEIGHTS_SPLINE:public PARTICLE_GRID_WEIGHTS<TV>
{
    typedef typename TV::SCALAR T;
    typedef VECTOR<int,TV::m> IV;
    typedef PARTICLE_GRID_WEIGHTS<TV> BASE;
    static_assert(degree>=1 && degree<=4);
public:
    enum {n=degree+1};
    struct PRECOMPUTE_DATA
    {
        IV base;
        VECTOR<TV,n> w,dw;
        TV X;
        TV m3;
        TV m4;
    };

    GRID<TV> grid;
    ARRAY<PRECOMPUTE_DATA> precompute_data;

    PARTICLE_GRID_WEIGHTS_SPLINE(const GRID<TV>& grid,int threads=1);
    virtual ~PARTICLE_GRID_WEIGHTS_SPLINE();

    void Compute(const PRECOMPUTE_DATA& pd,typename BASE::SCRATCH& scratch,bool want_gradient,bool want_pseudo_gradient) const;
    void Compute(int p,typename BASE::SCRATCH& scratch,bool want_gradient,bool want_pseudo_gradient) const override;
    void Compute(const TV& X,typename BASE::SCRATCH& scratch,bool want_gradient,bool want_pseudo_gradient) const override;
    void Compute_Precompute_Data(PRECOMPUTE_DATA& pd,const TV& X) const;
    void Update(ARRAY_VIEW<const TV> X) override;
    void Particle_Ranges(ARRAY<RANGE<IV> >& ranges) const override;
//#####################################################################
};
}
#endif
