//#####################################################################
// Copyright 2012.
// This file is part of PhysBAM whose distribution is governed by the license contained in the accompanying file PHYSBAM_COPYREGHT.txt.
//#####################################################################
// Class PROGRAM_CONTEXT
//#####################################################################
#ifndef __PROGRAM_CONTEXT__
#define __PROGRAM_CONTEXT__

#include <Core/Arrays/ARRAY.h>
#include <Core/Arrays/ARRAY_VIEW.h>
#include <Core/Symbolics/INSTRUCTION.h>
namespace PhysBAM{
template<class T> struct PROGRAM;
template<class T>
struct PROGRAM_CONTEXT
{
    ARRAY<T> reg;
    ARRAY_VIEW<T,MEM_IN> data_in;
    ARRAY_VIEW<T,MEM_OUT> data_out;

    PROGRAM_CONTEXT(){}
    PROGRAM_CONTEXT(const PROGRAM<T>& prog){Initialize(prog);}
    void Initialize(const PROGRAM<T>& prog)
    {
        int r=Value(prog.num_reg),c=Value(prog.constants.m);
        int i=Value(prog.num_in),o=Value(prog.num_out);
        reg.Resize(r+i+o+c);
        auto* p=reg.Get_Array_Pointer();
        data_in.Set(p+r,prog.num_in);
        data_out.Set(p+r+i,prog.num_out);
        ARRAY_VIEW<T,MEM_CONST> data_const(p+r+i+o,prog.constants.m);
        data_const=prog.constants;
    }
    void Set(MEM_IN r,T x)
    {
        data_in(r)=x;
    }
    template<int m> void Set(MEM_IN r,const VECTOR<T,m>& x)
    {
        for(int i=0;i<m;i++) data_in(r+i)=x(i);
    }
    template<int m,int n> void Set(MEM_IN r,const MATRIX<T,m,n>& x)
    {
        for(int j=0;j<n;j++)
            for(int i=0;i<m;i++)
                data_in(r++)=x(i,j);
    }
    T Get(MEM_OUT r) const
    {
        return data_out(r);
    }
    template<int m> VECTOR<T,m> Get(MEM_OUT r) const
    {
        VECTOR<T,m> x;
        for(int i=0;i<m;i++) x(i)=data_out(r+i);
        return x;
    }
    template<int m,int n> MATRIX<T,m,n> Get(MEM_OUT r) const
    {
        MATRIX<T,m,n> x;
        for(int j=0;j<n;j++)
            for(int i=0;i<m;i++)
                x(i,j)=data_out(r++);
        return x;
    }
};
}
#endif
