// file: $isip/class/algo/Connection/conn_06.cc
// version: $Id: conn_06.cc 8269 2002-07-02 19:14:33Z gao $
//

// isip include files
//
#include "Connection.h"

// method: computeStreamConcantenate
//
// arguments:
//  AlgorithmData& output: (output) output data
//  const AlgorithmData& input: (input) input data
//
// return: a boolean value indicating status
//
// this method takes the concatenation of the input
//
boolean Connection::computeStreamConcatenate(AlgorithmData& output_a,
					     const AlgorithmData& input_a) {

  // clear the output
  //
  output_a.clear();

  if (implementation_d != CONCATENATE) {
    return Error::handle(name(), L"computeStreamConcantenate",
			 ERR, __FILE__, __LINE__);    
  }
  
  boolean res = true;

  res = output_a.assign(input_a);
  
  // possibly display the data
  //
  display(output_a, input_a, name());
  
  // exit gracefully
  //
  return res;
}


// method: computeStreamSelect
//
// arguments:
//  AlgorithmData& output: (output) output data
//  const Vector<AlgorithmData>& input: (input) input data
//
// return: a boolean value indicating status
//
// this method takes the selection of the input
//
boolean Connection::computeStreamSelect(AlgorithmData& output_a,
					const Vector<AlgorithmData>& input_a) {
  
  // clear the output
  //
  output_a.clear();
  
  boolean res = true;

  // check for a valid channel
  //
  if (channel_d >= input_a.length()) {
    return Error::handle(name(), L"computeStreamSelect", Error::ARG,
			 __FILE__, __LINE__);
  }
  
  // algorithm: STREAM
  //  for this mode, we build one multichannel signal out of multiple
  //  multichannel signals.
  //
  
  // implementation: SELECT    
  //  build a new output signal which includes the specified channel
  //  from each input.
  //
  if (implementation_d != SELECT) {
    return Error::handle(name(), L"computeStreamSelect",
			 ERR, __FILE__, __LINE__);    
  }

  res &= output_a.assign(input_a(channel_d));

  // possibly display the data
  //
  display(output_a, input_a, name());
  
  // exit gracefully
  //
  return res;
}


// method: computeChannelConcatenate
//
// arguments:
//  VectorFloat& output: (output) output data
//  const Vector<AlgorithmData>& input: (input) input data
//
// return: a boolean value indicating status
//
// this method takes the concatenation of the input
//
boolean Connection::computeChannelConcatenate(VectorFloat& output_a,
					      const Vector<AlgorithmData>&
					      input_a) {

  // clear the output
  //
  output_a.clear();

  if (implementation_d != CONCATENATE) {
    return Error::handle(name(), L"computeChannelConcatenate",
			 ERR, __FILE__, __LINE__);    
  }
  
  //  arrange one multiple-channel signal in such a way that all the
  //  data in one channel is followed by all the data in other channel
  //  the output will be a single channel signal
  //

  // take one vector from each stream and concatenate it into one big
  // feature vector
  //
  long nelem = input_a.length();
  for (long i = 0; i < nelem; i++) {
    if (input_a(i).getVectorFloat().length() != 0)
      output_a.concat(input_a(i).getVectorFloat());
  }
  
  // possibly display the data
  //
  display(output_a, input_a, name());
  
  // exit gracefully
  //
  return true;
}



// method: computeChannelInterleave
//
// arguments:
//  VectorFloat& output: (output) output data
//  const Vector<AlgorithmData>& input: (input) input data
//
// return: a boolean value indicating status
//
// this method takes the interleave of the input
//
boolean Connection::computeChannelInterleave(VectorFloat& output_a,
					     const Vector<AlgorithmData>&
					     input_a) {

  // clear the output
  //
  output_a.clear();

  if (implementation_d != INTERLEAVE) {
    return Error::handle(name(), L"computeChannelInterleave",
			 ERR, __FILE__, __LINE__);    
  }
  // implementation: INTERLEAVE
  //  arrange one multiple-channel signal in such a way that the data
  //  in one channel is interleaved with data in other channel
  //  the output will be a single channel signal
  //

  // check the number of rows
  //
  long nrow = input_a.length();
  
  if (nrow == 0) {
    return true;
  }
  
  // grab only one channel for each input to get the input length
  //
  long ncol = input_a(0).getVectorFloat().length();
  output_a.setLength(nrow * ncol);
  
  // make sure each input has the same length
  //
  for (long i = 1; i < nrow; i++) {
    if (input_a(i).getVectorFloat().length() != ncol) {
      return Error::handle(name(), L"computeChannelInterleave",
			   ERR_LENGTH, __FILE__, __LINE__);
    }
  }
  
  // concatenate this channel to the output vector
  //
  for (long i = 0; i < ncol; i++) {
    for (long j = 0; j < nrow; j++) {
      output_a(i * nrow + j) = input_a(j).getVectorFloat()(i);
    }
  }
  
  // possibly display the data
  //
  display(output_a, input_a, name());

  // exit gracefully
  //
  return true;
}


