// subindices.h
#if !defined( _SUBINDICES_H_ )
#define _SUBINDICES_H_

//////////////////////////////////////////////////////////////////
// Clase para acumular los subíndices. Básicamente crea una lista
// con los subíndices de un elemento determinado, [][][]
class CSubindices
{
    int *m_pSubindices;   // matriz para los subíndices
    int m_nSubindices;    // número total de subíndices
    int *m_pSiguienteInd; // localización del siguiente subíndice
    int m_nSubindsActual; // subíndices que hay actualmente
  public:
    CSubindices(int nTotalSubinds, int PrimerSubind);
    ~CSubindices() { delete [] m_pSubindices; }
    int nSubindsActual() { return m_nSubindsActual; }
    void AnyadirSigSubind(int subind);
    int Desplazamiento(CDimensiones &dims) const;
};

CSubindices::CSubindices(int nTotalSubinds, int PrimerSubind)
{
  if (nTotalSubinds < 1)
  {
    cerr << "Número de subíndices incorrecto\n";
    nTotalSubinds = 1;
    PrimerSubind = 0;
  }
  m_pSubindices = m_pSiguienteInd = new int[m_nSubindices = nTotalSubinds];
  *m_pSiguienteInd++ = PrimerSubind;
  m_nSubindsActual = 1;
}

// Añadir el siguiente subíndice de un elemento a su matriz
// de subíndices
void CSubindices::AnyadirSigSubind(int subind)
{
  if (m_nSubindsActual < m_nSubindices)
  {
    *m_pSiguienteInd++ = subind;
    m_nSubindsActual++;
  }
}

// Calcular el desplazamiento en el espacio físico de la matriz,
// correspondiente a los subíndices del elemento elegido.
// Físicamente es una matriz lineal.
int CSubindices::Desplazamiento(CDimensiones &dims) const
{
  int desplazamiento = 0; // resultado
  int *pSubind = m_pSubindices; // subíndices del elemento accedido
  const int *dimension = dims.DimensionesMatriz(); // dimensiones
  int nDims = dims.nDimensiones();

  while (nDims--)
  {
    // Verificar si los subíndices están dentro del rango
    if (*pSubind < 0 || *pSubind >= *dimension)
    {
      cerr << "Subíndice fuera de rango\n";
      return -1;
    }
    desplazamiento += *pSubind++;
    if (nDims) desplazamiento *= *++dimension;
  }
  return desplazamiento;
}
//////////////////////////////////////////////////////////////////

#endif // _SUBINDICES_H_

