
#include "circuit.h"

// ************************** Circuit ***************

Circuit::Circuit(unsigned int inputs, unsigned int outputs)
: //	_inputs(inputs),
	_outputGates(outputs),
  //	_inputCount(inputs),
	_outputCount(outputs)
{//	for(int i = 0; i < _inputCount ; i++)
 //		_inputs[i] = NULL;
	// Derived classes construct the gates and define
	// the ouputs in constructors.
	// Inputs should be params of the constructors
}

Array<Boolean> Circuit::output()
{	Array<Boolean> result(_outputCount);
	for(int i = 0; i < _outputCount; i++)
		if(_outputGates[i])
			result[i] = _outputGates[i]->output();
		else
			result[i] = false;
	return result;
}

/*
void Circuit::connect(unsigned int which, Gate * g)
{	if(which < _inputCount)
		_inputs[which] = g;
}
// If these two are included, then they must be overridden
// in each derived class to reconntct the internals.
// Perhaps these should be pure virtual if present.

void Circuit::connect(unsigned int which, Circuit c, unsigned int n)
{	if(which < _inputCount)
		_inputs[which] = c.output(n);
}
*/

Gate * Circuit::output(unsigned int n)
{	return (n < _outputCount)?_outputGates[n]:NULL;
}

// ************************** Adder ***************

Adder::Adder(Gate* in1, Gate* in2)
:	Circuit(2,2)
{	if(!in1 || ! in2)
   	userERROR("NULL Gates are not legal.");
//	_inputs[0] = in1;
//	_inputs[1] = in2;

	_outputGates[0] = &_combine;
	_outputGates[1] = &_carry;

	_flipLeft.connect(in1);
	_flipRight.connect(in2);

	_left.connect(in1);
	_left.connect(&_flipRight);

	_right.connect(in2);
	_right.connect(&_flipLeft);

	_combine.connect(&_left);
	_combine.connect(&_right);

	_carry.connect(in1);
	_carry.connect(in2);
}

// ************************** FullAdder ***************

FullAdder::FullAdder(Gate* in1, Gate* in2, Gate* carryIn)
:	Circuit(3,2),
	_AB(in1, in2),
	_RC(_AB.output(0), carryIn) // AB already constructed
{//  _inputs[0] = in1;     // Inputs not used here actually.
 //	_inputs[1] = in2;
 //	_inputs[2] = carryIn;
	_outputGates[0] = _RC.output(0);
	_outputGates[1] = &_carryOut;
	_carryOut.connect(_AB.output(1));
	_carryOut.connect(_RC.output(1));

}


