//#####################################################################
// Copyright 2012-2025 Craig Schroeder.
// This file is part of PhysBAM whose distribution is governed by the license contained in the accompanying file PHYSBAM_COPYREGHT.txt.
//#####################################################################
// Class COMPILER_DATA
//#####################################################################
#ifndef __COMPILER_DATA__
#define __COMPILER_DATA__

#include <Core/Arrays/ARRAY.h>
#include <Core/Symbolics/REG.h>
#include <string>
namespace PhysBAM{

template<class T>
struct COMPILER_DATA
{
    enum class TYPE{scalar,vec,mat,undef};
    COMPILER_DATA()=default;
    COMPILER_DATA(REG r)
        :type(TYPE::scalar),x{r}
    {}
    COMPILER_DATA(int mm)
        :type(TYPE::vec),x(mm),m(mm)
    {}
    COMPILER_DATA(int mm,int nn)
        :type(TYPE::mat),x(mm*nn),m(mm),n(nn)
    {}

    TYPE type=TYPE::undef;
    ARRAY<REG> x; // vec or matrix
    int m=0,n=0;
    COMPILER_DATA* ref=nullptr;

    bool Same_Type(const COMPILER_DATA& d) const
    {
        return type==d.type && m==d.m && n==d.n && x.m==d.x.m;
    }

    void Set_Type(const COMPILER_DATA& d)
    {
        type=d.type;
        x.Resize(d.x.m);
        m=d.m;
        n=d.n;
    }

    void Set_Type()
    {
        type=TYPE::scalar;
        x.Resize(1);
        m=0;
        n=0;
    }

    void Set_Type(int mm)
    {
        type=TYPE::vec;
        x.Resize(mm);
        m=mm;
        n=0;
    }

    void Set_Type(int mm,int nn)
    {
        type=TYPE::mat;
        x.Resize(mm*nn);
        m=mm;
        n=nn;
    }

    std::string Type_Str() const;
    REG& operator()(int i,int j){assert(type==TYPE::mat);return x(m*j+i);}
    const REG& operator()(int i,int j) const {assert(type==TYPE::mat);return x(m*j+i);}
};
}
#endif
