/*Isaac Sarver
Started 9/16/10
Converted to char on 9/19/10. The DeleteHead() does not currently maintain the indexing. That code is commented out.
This is the class for a linked function of chars. It will be unsorted, indexed, and doublely linked.*/
#include
#include
#include"Function.h"
using namespace std;
Function Function::Linear(double Theta, Function That)
{
Function Out;
Spot A;
double Sin= sin(Theta), Cos = cos(Theta);
nodeptr n = head, m = That.head;
while(n != NULL) //Current implementation suggests that the mesh points will always line up
{
A.x_i = n->value.x_i; //get x_i
A.y_i = Cos*m->value.y_i+Sin*n->value.y_i; //calculate new y_i
A.dy_i = Cos*m->value.dy_i+Sin*n->value.dy_i; //calculate new dy_i
Out.AddTail(A);
n = n->next; //Advance pointers
m = m->next;
}
return(Out);
}
void Function::Scale(double Norm)
{
nodeptr n = head;
double scale = sqrt(Norm);
while(n != NULL)
{
n->value.y_i = n->value.y_i/scale;
n->value.dy_i = n->value.dy_i/scale;
n = n->next;
}
return;
}
void Function::SetE(double Energy) //Set all of the energies not in the tail
{
nodeptr Pointer = head;
while(Pointer != NULL)
{
Pointer->value.E = Energy;
Pointer = Pointer->next;
}
return;
}
void Function::SetAsy(double A[2]) //user sets the asymptotic behavoir
{
a = A[0];
b = A[1];
set = true;
return;
}
bool Function::Receive(double A[2]) //Places the values of the asymptotic behavoir in the array {a,b}
{
A[0] = a;
A[1] = b;
return(set);
}
bool Function::ChangePoint(Spot x, nodeptr A) //Change Node at pointer
{
if(A->value.x_i == x.x_i) //will only overwrite if the value belongs
{
A->value = x; //If the point is known, then don't go looking for it
return(true); //returns if successful
}
return(false);
}
void Function::AddHead(Spot x) //Add Node to Head
{
nodeptr n = new node; //General node pointer
n->value = x; //Store new value in n
n->prev = NULL; //Point previous to NULL
n->next = NULL; //Point next to NULL, there may not be a next node if empty function
count++; //Increament size
if(head == NULL) //If empty function
{
head = n; //Point head and tail to n
tail = n;
}
else if(x.x_i == head->value.x_i) //if replacing the head
{
head->value = x; //store the value
count--; //decreament counter as this not a new point
}
else //new head of non-empty function
{
n->next = head; //point next at present head
head->prev = n; //point prev of next node, which is head, to n
head = n; //point head at new head node
}
return;
}
void Function::AddTail(Spot x) //Add Node to Tail
{
nodeptr n = new node; //General node pointer
n->value = x; //Store new value in n
n->prev = NULL; //Point previous to NULL, there may not be a previous node if empty function
n->next = NULL; //Point next to NULL
count++; //Increament size
if(tail == NULL) //If empty function
{
head = n; //Point head and tail to n
tail = n;
}
else if(x.x_i == tail->value.x_i) //if replacing the tail
{
tail->value = x; //store the point
count--; //decreament counter as this not a new point
}
else //if new tail of non-empty function
{
n->prev = tail; //point prev at present tail
tail->next = n; //point next of prev node, which is tail, to n
tail = n; //point tail at new node
}
return;
}
void Function::AddPoint(Spot x) //Add Node point x_i, overwrites if already present
{
nodeptr n = new node; //New node pointer
nodeptr loc = head; //Location node pointer
if(count == 0 || x.x_i <= head->value.x_i) //if the function is empty, or the point goes before the head, or changes the head
{
AddHead(x);
}
else if(x.x_i > head->value.x_i && x.x_i < tail->value.x_i) //Execute only if the given an is between the head and tail. This algorithm will error if the element is to be inserted at the head or tail, will call the correct function if so.
{
n->value = x; //Store new value in n
n->prev = NULL; //Point previous to NULL
n->next = NULL; //Point next to NULL, there may not be a next node if empty function
count++; //Increament size
while(loc->value.x_i < x.x_i) //while loc is less than the point in mind
{
loc = loc->next; //advance location
}
if(loc->value.x_i != x.x_i) //if not the point in mind, loc goes on the greater than side
{
n->next = loc; //point next at location
n->prev = loc->prev; //point prev of n to what will be previous of loc
loc->prev->next = n; //point node prev to loc at n
loc->prev = n; //point loc prev at n
}
else //if it is the point in mind
{
loc->value = x; //store the point
count--; //decreament counter as this not a new point
}
}
else //Only range greater than or equal to the largest value has not been covered, no need to check
{
AddTail(x);
}
return;
}
Spot Function::DeleteHead() //Delete first Node
{
nodeptr n = head; //General n point and point it at the node to go away
Spot deleted; //Value to be returned
if(n != NULL) //If the function isn't already empty
{
deleted = head->value; //Inside the conditional or it will trigger segfault
count--; //Decreament the counter
if(head->next != NULL) //I think this next line will cause a Seg Fault if executed with only 1 in the function. Not an issue with DeleteIndex as this function will be called to do that.
{
head = head->next; //Advance head
}
head->prev = NULL; //Point the new head's previous into the void
n->next = NULL; //Disconnect n from function
delete n; //Delete n
}
if(count == 0) //To return the function to the orginal state to accept new nodes without ill effect
{
head = NULL;
tail = NULL;
}
return(deleted);
}
Spot Function::DeleteTail() //Delete last Node
{
nodeptr n = tail; //General n point and point it at the node to go away
Spot deleted; //Value to be returned
if(n != NULL) //If the function isn't already empty
{
deleted = tail->value; //Value to be returned
count--; //Decreament the counter
if(tail->prev != NULL) //I think this line will cause a Seg Fault if function of 1
{
tail = tail->prev; //Advance tail
}
tail->next = NULL; //Point the new tail's next into the void
n->prev = NULL; //Disconnect n from function
delete n; //Delete n
}
if(count == 0) //To return the function to the orginal state to accept new nodes without ill effect
{
head = NULL;
tail = NULL;
}
return(deleted);
}
Spot Function::WhatValue(double x, nodeptr p)
{
nodeptr n = p; //To remove access to outside pointer
if(n->value.x_i == x)
return(n->value); //If the pointer is the point in question, return value
while(n->prev->value.x_i < x && n->value.x_i < x && n != tail) //While too small to interpolate
n = n->next; //Advance pointer
while(n->prev->value.x_i > x && n->value.x_i > x && n != head) //While too big to interpolate
n = n->prev; //Demote pointer
//If the point does not exist in the function, do a linear interpolation of the slope and a quadratic interpolation of the value (I think it is 'quadratic spline')
Spot Values; //value to be returned
double x1 = n->prev->value.x_i; //I don't want to mess with pointer ops in the interpolation
double x2 = n->value.x_i;
double y1 = n->prev->value.y_i;
double y2 = n->value.y_i;
double dy1 = n->prev->value.dy_i;
double dy2 = n->value.dy_i;
//Useful values
double m = (dy2-dy1)/(x2-x1); //average slope of the slope
double xbar = (x1+x2)/2.0; //average x
double dybar = (dy1+dy2)/2.0; //average dy
Values.x_i = x; //the point of interest
Values.y_i = m*x*x/2.0-m*xbar*x+dybar*x+(y1+y2)/2.0+m*xbar*xbar/2.0-dybar*xbar; //the quadratic interpolation of y at the point
Values.dy_i = m*x-m*xbar+dybar; //the linear interpolation of y' at the point
return(Values);
}
Spot Function::WhatValue(double x) //Returns value at point x_i, interpolates if needed
{
nodeptr n = head; //General node pointer and start at the head
if(tail->value.x_i == x) //if tail is the point of interest. no need to search the whole function for it if it is at the end
return(tail->value);
while(n->next != NULL && n->value.x_i < x) //While the point is not found and n has not found the end of the function
{
n = n->next; //Advance n
}
if(n->value.x_i == x) //if the point was exactly found, return the value.
return(n->value);
//If the point does not exist in the function, do a linear interpolation of the slope and a quadratic interpolation of the value (I think it is 'quadratic spline')
Spot Values; //value to be returned
double x1 = n->prev->value.x_i; //I don't want to mess with pointer ops in the interpolation
double x2 = n->value.x_i;
double y1 = n->prev->value.y_i;
double y2 = n->value.y_i;
double dy1 = n->prev->value.dy_i;
double dy2 = n->value.dy_i;
//Useful values
double m = (dy2-dy1)/(x2-x1); //average slope of the slope
double xbar = (x1+x2)/2.0; //average x
double dybar = (dy1+dy2)/2.0; //average dy
Values.x_i = x; //the point of interest
Values.y_i = m*x*x/2.0-m*xbar*x+dybar*x+(y1+y2)/2.0+m*xbar*xbar/2.0-dybar*xbar; //the quadratic interpolation of y at the point
Values.dy_i = m*x-m*xbar+dybar; //the linear interpolation of y' at the point
return(Values);
}
Spot Function::WhatValue(nodeptr n) //Returns value at pointer
{
if(n == NULL)
{
Spot X;
X.x_i = 0;
X.y_i = 0;
X.dy_i = 0;
return(X);
}
return(n->value);
}
int Function::Size() //Returns the length of the function
{
return(count);
}
Function::nodeptr Function::Head()
{
return(head);
}
Function::nodeptr Function::Tail()
{
return(tail);
}
Function::nodeptr Function::Adv(nodeptr x)
{
return(x->next);
}
Function::nodeptr Function::Demote(nodeptr x)
{
return(x->prev);
}
void Function::Print() //Returns first index of value if value is in function, -1 if not
{
nodeptr n = head; //General node pointer and start at the head
while(n != NULL) //While the index is not found and n has not fallen off the end of the function
{
cerr << "y(" << n->value.x_i << ") = " << n->value.y_i << "\ty'(" << n->value.x_i << ") = " << n->value.dy_i << endl; //Print value
n = n->next; //Advance n
}
cerr << endl;
return;
}
bool Function::operator==(Function & other)
{
bool truth = true; //Assume true
nodeptr n = head;
nodeptr m = other.head;
if(count == other.count) //If both are same length
{
if(count == 0) //If size is zero
{
if(head != other.head) //check to see if both heads are pointing at same place, only happening if NULL
{
truth = false;
}
else if(tail != other.tail) //check to see if both tails are point at same place, only happening if NULL
{
truth = false;
}
}
else //If non-zero size
{
if(!(set == other.set && a == other.a && b == other.b)) //If private data is not the same
{
truth = false;
}
while(n != NULL && truth) //While the pointer hasn't fallen off of the cliff or the functions are found to not be equal
{
if(n->value != m->value) //If current position is not equal
{
truth = false;
}
n = n->next; //Advance pointers
m = m->next;
}
}
}
else //Not same size
{
truth = false;
}
return(truth);
}
void Function::operator=(Function other)
{
nodeptr m = other.head;
while(count != 0) //Clear out the present object
{
DeleteTail();
}
while(m != NULL) //Until m runs off the tail of the other object
{
AddTail(m->value); //Add the value at m to the tail of the present object
m = m->next; //Advance pointer
}
set = other.set; //copy in set, a, and b from other object
a = other.a;
b = other.b;
return;
}