//////////////////////////////////////////////////////////////////////////////
//
// File: nn_layer.cc
//
// Purpose: Implementation for NeuNet's Layer class.
//
// Authors:
//   txe  Travis Emmitt
//
// Modifications:
//   17-APR-1998  txe  Initial creation
//   19-APR-1998  txe  Cleaned up, added constructor, destructor
//   20-APR-1998  txe  Purifying...
//   23-APR-1998  txe  Using static debug, changed constructor
//
//////////////////////////////////////////////////////////////////////////////

#include <stdio.h>
#include <stdlib.h>
#include "common.h"
#include "nn_arch.h"
#include "nn_node.h"
#include "nn_layer.h"

//////////////////////////////////////////////////////////////////////////////
// Note: you have to construct layers in reverse order! (so next is valid)
//////////////////////////////////////////////////////////////////////////////

Layer::Layer (char *name, Arch *arch, int num_nodes, int num_in, Layer *next)
     : Debug (name) {

  ASSERT (num_nodes > 0);

  this->arch      = arch;
  this->next      = next;
  this->num_nodes = num_nodes;

  if ((this->nodes = new Node *[num_nodes]) == NULL) {
    ERR << name << " couldn't create nodes[]; out of memory!\n";
    ERR << "  (array of size " << num_nodes << ")\n";
    exit (-1);
  }

  char temp[NAME_LEN+1];
  int num_out = (next ? next->num_nodes : 0);

  for (int i = 0; i < num_nodes; i++) {
    sprintf (temp, "%s.%d", name, i);

    if ((nodes[i] = new Node (temp, arch, num_in, num_out)) == NULL) {
      ERR << name << " couldn't create nodes[" << i << "]; out of memory!\n";
      exit (-1);
    }

    for (int j = 0; j < num_out; j++) {
      ASSERT (next->nodes != NULL);
      ASSERT (next->nodes[j] != NULL);
      nodes[i]->SetLink (i, j, next->nodes[j]);
    }
  }

  DEBUG(1) << "Layer " << name << " created with " << num_nodes << " nodes, "
	   << num_in << " in_links, and " << num_out << " out_links\n";
}

//////////////////////////////////////////////////////////////////////////////

Layer::~Layer () {
  ASSERT (num_nodes > 0);
  ASSERT (nodes != NULL);

  DEBUG(DEL) << "Destroying " << name << "'s nodes (there are "
	     << num_nodes << ")...\n";

  for (int i = 0; i < num_nodes; i++) {
    ASSERT (nodes[i] != NULL);
    delete nodes[i];
  }

  DEBUG(DEL) << "Destroying " << name << "'s nodes[]\n";
  DELETE_ARRAY nodes;

  DEBUG(DEL) << "Destroying " << name << "\n";
}

//////////////////////////////////////////////////////////////////////////////

