#include "CellularAutomaton.h"

#include <cassert>

//#define VERBOSE
#ifdef VERBOSE
#include <cstdio>
#endif

CellularAutomaton::CellularAutomaton( const AlleleType *c, unsigned int n, const AlleleType *r ) :
    chromosome( c ), ruleLUT( r ), numBits( n / 2u ), iteration( 0u ), bits( new char[numBits+1] ) {
  assert( chromosome );
  for ( unsigned int i = 0u; i < n; i += 2u ) {
    assert( chromosome[i] == static_cast<AlleleType>( 0 ) ||
            chromosome[i] == static_cast<AlleleType>( 1 ) );
    bits[i/2u] = static_cast<bool>( chromosome[i] ) ? '1' : '0';
  }
  bits[numBits] = '\0';
}

CellularAutomaton::~CellularAutomaton() {
  delete[] bits;
}

unsigned int CellularAutomaton::getNumBits() const {
  return numBits;
}

const char * CellularAutomaton::getStorage() const {
  return bits;
}

unsigned int CellularAutomaton::getIteration() const {
  return iteration;
}

AlleleType CellularAutomaton::getRule( unsigned int index ) const {
  if ( ruleLUT )
    return ruleLUT[ chromosome[index*2u+1u] ];
  else
   return chromosome[index*2u+1u];
}

char CellularAutomaton::getBit( unsigned int index, unsigned int state ) const {
  AlleleType rule = getRule( index );
  char bit = static_cast<bool>(( rule >> state ) & 0x1 ) ? '1' : '0';
#ifdef VERBOSE
  std::printf( "getBit(%02d) state::%x rule::%03u bit::%c\n", index, state, rule, bit );
#endif
  return bit;
}

void CellularAutomaton::createVector() {
  unsigned int state = (( bits[numBits-2u] - '0' ) << 2 ) |
                       (( bits[numBits-1u] - '0' ) << 1 ) |
                       ( bits[0u] - '0' );
  char tempBit = getBit( numBits - 1u, state );
  for ( unsigned int i = 0u;i < ( numBits - 1u );i++ ) {
    state = (( state << 1 ) & 0x7 ) | ( bits[i+1u] - '0' );
    bits[i] = getBit( i, state );
  }
  bits[numBits-1u] = tempBit;
  iteration++;
}
