/* ************************************************************* 

        Final Project                                 MMU 1996

        ######################################################
        #                                                    # 
        #               A Logical Neural Network             #    
        #                                                    #
        #               A single Ram Unit                    #
        #                                                    # 
        ###################################################### 
 
        Albrecht Schmidt                              17.09.96 
 
        FILE: CRam.C                               Version 1.0 
 
   ************************************************************* */ 
#include <iostream.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#include "CSupport.h"
#include "CRam.h"

// #define DP(X) cout << X ;
#define DP(X) ;



void CRam::error(char *msg)
{
  cerr << "\nERROR:" << msg;
  exit(-1);
}


void CRam::warning(char *msg)
{
  cerr << "\nWARNING:" << msg;
}

CRam::CRam(int no_inp)
{
  DP("\nCRam::CRam(" << no_inp << ")");

  inputs  = no_inp;
  ramsize = (long) pow(2, inputs);

  // cout << "\nRamsize: " << ramsize;

  if ((memory = new ramState[ramsize]) <= 0)
  {
     error("Can't allocate memory [CRam::CRam(...)] !!!");
  }
  Reset();
}

CRam::~CRam()
{
  DP("\nCRam::~CRam()");

  delete [] memory;
}


CRam::CRam(FILE *fd)
{
  DP("\nCRam::CRam(" << fd << ")");

  char comment[100];
  // Read the class variables, read the comment but don't use it.
  fscanf(fd, "%li %s\n", &ramsize, comment);
  fscanf(fd, "%i %s\n", &inputs, comment);

  // cout << "\nRamsize: " << ramsize;

  if ((memory = new ramState[ramsize]) <= 0)
  {
     error("Can't allocate memory [CRam::CRam(...)] !!!");
  }
  Reset();

  long address;
  char buf[100];
  while ( !feof(fd) )
  {
	fscanf( fd, "%s \n", buf);
	if (buf[0] == '-') break;
	else
	{
	   sscanf(buf, "%li", &address);
	   Store(address, on);
	}
  }
}


void CRam::Save(FILE *fd)
{
  DP("\nCRam::Save(" << fd << ")");

  fprintf(fd, "%li :ramsize\n", ramsize);
  fprintf(fd, "%i :inputs\n", inputs);

  // write the addresses of units that are on
  int i;
  for(i=0;i<ramsize;i++)
    if (memory[i]==on)
       fprintf( fd, "%i\n", i);

  fprintf(fd , "---------\n" );
}



int CRam::Store(double *add, int len, ramState val)
{
  DP("\nCRam::Store(" << add << ", " << len << ", " << val << ")");

  return Store(Vect2int(add, len), val);
}


int CRam::Store(long add, ramState val)
{
  DP("\nCRam::Store(" << add << ", " << val << ")");

  if (add < ramsize)
  {
    memory[add] = val;
    return 1;
  }
  else
  {
     warning("Address out of range [CRam::Store] !!!");
     return -1;
  }
}

ramState CRam::Recall(double *add, int len)
{
  DP("\nCRam::Recall(" << add << ", " << len << ")");

  return Recall(Vect2int(add, len));
}



ramState CRam::Recall(long add)
{
  DP("\nCRam::Recall(" << add << ")");


  if (add < ramsize)
  {
    return memory[add];
  }
  else
  {
     warning("Address out of range [CRam::Recall] !!!");
     return off;
  }
}

void CRam::Reset()
{
  DP("\nCRam::Reset()");

  long i;
  for(i=0;i<ramsize;i++)
      memory[i] = off;
}


void CRam::Print()
{
  DP("\nCRam::Print()");

  long i;
  cout << "\n ramsize: " << ramsize;
  for(i=0;i<ramsize;i++)
      cout << "\nmemory[" << i << "] = " << memory[i] ;
}


long CRam::Vect2int(double *vect, int len)
{
  DP("\nCRam::Vect2int(" << vect << ", " << len << ")");

  long i,
       help =1,
       sum = 0;

  for(i=0;i<len;i++)
  {
    if (vect[i] == 1)  sum = sum + help;
    help = help + help;
  }

  return sum;
}


