/*
 * Copyright © 2007-2026 Dynare Team
 *
 * This file is part of Dynare.
 *
 * Dynare is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Dynare is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Dynare.  If not, see <https://www.gnu.org/licenses/>.
 */

#ifndef COMMON_ENUMS_HH
#define COMMON_ENUMS_HH

#include <string>

using namespace std;

//! Enumeration of possible symbol types
/*! Warning: do not to change existing values for 0 to 4: the values matter for homotopy_setup
 * command */
enum class SymbolType
{
  endogenous = 0,              // Endogenous (non-heterogeneous)
  exogenous = 1,               // Exogenous (non-heterogeneous)
  exogenousDet = 2,            // Exogenous deterministic (non-heterogeneous)
  parameter = 4,               // Parameter (non-heterogeneous)
  heterogeneousEndogenous = 5, // Endogenous that is heterogeneous across some dimension
  heterogeneousExogenous = 6,  // Exogenous that is heterogeneous across some dimension
  heterogeneousParameter = 7,  // Parameter that is heterogeneous across some dimension
  modelLocalVariable = 10,     // Local variable whose scope is model (pound expression)
  modFileLocalVariable = 11,   // Local variable whose scope is mod file (model excluded)
  externalFunction = 12,       // External (user-defined) function
  trend = 13,                  // Trend variable
  statementDeclaredVariable
  = 14, //!< Local variable assigned within a Statement (see subsample statement for example)
  logTrend = 15, //!< Log-trend variable
  unusedEndogenous
  = 16, //!< Type to mark unused endogenous variables when `nostrict` option is passed
  databaseVariable = 17, // Variable inside a database namespace
  epilogue = 18,         //!< Variables created in epilogue block
  excludedVariable = 19  //!< Variable excluded via model_remove/var_remove/include_eqs/exclude_eqs
};

constexpr bool
isHeterogeneous(SymbolType type)
{
  return type == SymbolType::heterogeneousEndogenous || type == SymbolType::heterogeneousExogenous
         || type == SymbolType::heterogeneousParameter;
}

constexpr string
to_string(SymbolType type)
{
  using enum SymbolType;
  switch (type)
    {
    case endogenous:
      return "endogenous";
    case exogenous:
      return "exogenous";
    case exogenousDet:
      return "exogenousDet";
    case parameter:
      return "parameter";
    case modelLocalVariable:
      return "modelLocalVariable";
    case modFileLocalVariable:
      return "modFileLocalVariable";
    case externalFunction:
      return "externalFunction";
    case trend:
      return "trend";
    case statementDeclaredVariable:
      return "statementDeclaredVariable";
    case logTrend:
      return "logTrend";
    case unusedEndogenous:
      return "unusedEndogenous";
    case databaseVariable:
      return "databaseVariable";
    case epilogue:
      return "epilogue";
    case excludedVariable:
      return "excludedVariable";
    case heterogeneousEndogenous:
      return "heterogeneousEndogenous";
    case heterogeneousExogenous:
      return "heterogeneousExogenous";
    case heterogeneousParameter:
      return "heterogeneousParameter";
    }
  __builtin_unreachable(); // Silence GCC warning
}

enum class UnaryOpcode
{
  uminus,
  exp,
  log,
  log10,
  cos,
  sin,
  tan,
  acos,
  asin,
  atan,
  cosh,
  sinh,
  tanh,
  acosh,
  asinh,
  atanh,
  sqrt,
  cbrt,
  abs,
  sign,
  steadyState,
  steadyStateParamDeriv,    // for the derivative of the STEADY_STATE operator w.r.t. to a parameter
  steadyStateParam2ndDeriv, // for the 2nd derivative of the STEADY_STATE operator w.r.t. to a
                            // parameter
  expectation,
  erf,
  erfc,
  diff,
  sum
};

enum class BinaryOpcode
{
  plus,
  minus,
  times,
  divide,
  power,
  powerDeriv, // for the derivative of the power function (see trac ticket #78)
  equal,
  max,
  min,
  less,
  greater,
  lessEqual,
  greaterEqual,
  equalEqual,
  different
};

// Small number value used when evaluating powerDeriv opcodes.
// Put here instead of inside BinaryOpNode class, because needed by bytecode MEX.
constexpr double power_deriv_near_zero {1e-12};

enum class TrinaryOpcode
{
  normcdf,
  normpdf
};

enum class PriorDistributions
{
  noShape = 0,
  beta = 1,
  gamma = 2,
  normal = 3,
  invGamma = 4,
  invGamma1 = 4,
  uniform = 5,
  invGamma2 = 6,
  dirichlet = 7,
  weibull = 8
};

enum class EquationType
{
  evaluate, //!< Simple evaluation, normalized variable on left-hand side (written as such by the
            //!< user)
  evaluateRenormalized, //!< Simple evaluation, normalized variable on left-hand side (normalization
                        //!< computed by the preprocessor)
  solve                 //!< No simple evaluation of the equation, it has to be solved
};

enum class BlockSimulationType
{
  evaluateForward = 1,       //!< Simple evaluation, normalized variable on left-hand side, forward
  evaluateBackward,          //!< Simple evaluation, normalized variable on left-hand side, backward
  solveForwardSimple,        //!< Block of one equation, newton solver needed, forward
  solveBackwardSimple,       //!< Block of one equation, newton solver needed, backward
  solveTwoBoundariesSimple,  //!< Block of one equation, Newton solver needed, forward and backward
  solveForwardComplete,      //!< Block of several equations, Newton solver needed, forward
  solveBackwardComplete,     //!< Block of several equations, Newton solver needed, backward
  solveTwoBoundariesComplete //!< Block of several equations, Newton solver needed, forward and
                             //!< backwar
};

enum class PacTargetKind
{
  unspecified, // Must be the first one, because it’s the default initializer
  ll,
  dl,
  dd
};

#endif
