//Neuron.cpp

#include "Neuron.h"

//numInputs=0, prevLayer=null, and weights=null for input layer
Neuron::Neuron(int numInputs, Neuron* prevLayer[], float weights[], int actFunction)
{
	numberOfInputs = numInputs;
	outputValue = 0;
	activationFunction = actFunction;

	if (numberOfInputs != 0) //this is a "normal layer"
	{
		inputList = new Neuron*[numberOfInputs];
		for (int i=0; i<numberOfInputs; i++)
			inputList[i] = prevLayer[i];

		inputWeights = new float[numberOfInputs];
		for (int i=0; i<numberOfInputs; i++)
			inputWeights[i] = weights[i];
	}
	else //this is the input layer
	{
		inputList = 0;
		weights = 0;
	}
}

Neuron::~Neuron()
{
	if (numberOfInputs != 0) //not input layer
	{
		delete [] inputList;
		delete [] inputWeights;
	}
}

float Neuron::GetOutput()
{
	return outputValue;
}

void Neuron::SetOutput(float value)
{
	outputValue = value;
}

float* Neuron::GetInputWeights()
{
	return inputWeights;
}

void Neuron::CalculateOutput()
{
	if (numberOfInputs != 0) //this is a "normal layer"
	{
		outputValue = 0;

		//get sum of weighted inputs
		for (int i=0; i<numberOfInputs; i++)
		{
			outputValue += inputList[i]->GetOutput()*inputWeights[i];
		}

		//use one of the activation functions on this sum
		switch(activationFunction)
		{
			case 0: //sigmoid function
				outputValue = SigmoidFunction(outputValue);
				break;
			case 1: //sine function
				outputValue = SineFunction(outputValue);
				break;
			case 2: //threshold function
				outputValue = ThresholdFunction(outputValue);
				break;
			default:
				break;
		}
	}
	//else, this is the normal layer, in which case the output value
	//has already been set externally with SetOutput
}

float Neuron::ThresholdFunction(float input)
{
	if (input<0)
		return -1;
	else
		return 1;
}

float Neuron::SigmoidFunction(float input)
{
	float sigmoid = 1/(1 + exp(-input));
	return (sigmoid*2 - 1); //scaled to output values between -1.0 and 1.0
}

float Neuron::SineFunction(float input)
{
	return sin(input);
}
