/*********************************************************
** Copyright (c) 2005
** University of Washington
** Licensed under the terms set forth by University of
** Washington. If you did not sign such a license, you
** are using this software/code illegally and you do not
** have permission to use, modify, or redistribute
** this or any files in this software package.
**
** File: UpperDiagonalMatrix.cpp
**
**********************************************************/
#include "UpperDiagonalMatrix.h"
#include "ClusterException.h"
#include "SafeInt.h"

CUpperDiagonalMatrix::CUpperDiagonalMatrix(int size)
{
  m_iLength = (size*(size-1)/2);
  m_iSize = size;
  
  // Perf tested this - only improves by < 1 sec for 1000 x 112.
  __catch_badalloc(m_ppMatrix = new double*[m_iSize]);
  if (NULL == m_ppMatrix)
    __throw_cluster_ex(CLUSTEX_OUTOFMEMORY, "Could not allocate matrix");

  int i;
  for(i = 0; i < m_iSize; i++)
    {
      __catch_badalloc(m_ppMatrix[i] = new double[m_iSize]);
      if (NULL == m_ppMatrix[i])
	  goto CUDM_Constructor_OutOfMemory;
    }

  m_iConst = 2*size - 3;
  return;

 CUDM_Constructor_OutOfMemory:
  for(int j = 0; j < i; j++)
    delete m_ppMatrix[i];
  delete m_ppMatrix;
  __throw_cluster_ex(CLUSTEX_OUTOFMEMORY, "Could not allocate matrix");

}

CUpperDiagonalMatrix::~CUpperDiagonalMatrix()
{
  //free(m_pMatrix);
  for(int i = 0; i < m_iSize; i++)
    delete [] m_ppMatrix[i];
    delete m_ppMatrix;
}


void CUpperDiagonalMatrix::SetValue(int i, int j, double value)
{
  m_ppMatrix[i][j] = m_ppMatrix[j][i] = value;
}

double CUpperDiagonalMatrix::GetValue(int i, int j)
{
  return m_ppMatrix[i][j];
}

uintmax_t CUpperDiagonalMatrix::GetMemoryRequirement(uintmax_t size)
{
  uintmax_t sd = sizeof(double);
  uintmax_t m = CSafeInt<uintmax_t>::Multiply((uintmax_t)size, (uintmax_t)size);
  return CSafeUIntMax::Multiply(sd, m);
}

