Let's start with the addition operator. This one is used in code fragments like this:
Complex_POLY R,P,P2; //assume P and P2 have been built somehow R = P + P2;
The overloaded + operator is called to handle the P + P2 portion of the line and the result is returned to the right hand side so that the overloaded equal can be used update R. Note that addition is accomplished by using the insert_nosort() method so to delay sorting of the answer until the process is finished.
// ************************************ //
// Overloaded Operator + //
// ************************************ //
Complex_POLY Complex_POLY::operator+(const Complex_POLY& P)
{
unsigned int p;
Complex_POLY *RESULT;
if(head==NULL && P.head==NULL){
//both this and the incoming polynomial are degenerate
//cout << "Both this and incoming polynomial are degenerate" << endl;
RESULT = new Complex_POLY();
return(*RESULT);
}
if(head!=NULL && P.head==NULL){
//we add nothing, so return *this
return(*this);
}
if(head==NULL && P.head!=NULL){
//*this is NULL, so return incoming P
*RESULT = P;
return(*RESULT);
}
if(head!=NULL && P.head!=NULL){
RESULT = new Complex_POLY();
*RESULT = *this;
Complex_POLY_CELL* temp;
for(ComplexPOLYIter next(P);next;++next){
temp = next();
RESULT->insert_nosort(temp->element,temp->power);
}
//insertions done, so now sort
RESULT->mergesort();
return(*RESULT);
}
}
Similar comments can be made about the subtraction operator.
// ************************************ //
// Overloaded Operator - //
// ************************************ //
Complex_POLY Complex_POLY::operator-(const Complex_POLY& P)
{
unsigned int p;
Complex_POLY *RESULT;
Complex s;
if(head==NULL && P.head==NULL){
//both this and the incoming polynomial are degenerate
//cout << "Both this and incoming polynomial are degenerate" << endl;
RESULT = new Complex_POLY();
return(*RESULT);
}
if(head!=NULL && P.head==NULL){
//we subtract nothing, so return *this
return(*this);
}
if(head==NULL && P.head!=NULL){
//*this is NULL, so return -P
RESULT = new Complex_POLY();
*RESULT = P;
Complex_POLY_CELL* temp;
temp = RESULT->head;
temp->element *= -1.0;
while(temp->next!=NULL){
temp->next->element *= -1.0;
temp = temp->next;
}
return(*RESULT);
}
if(head!=NULL && P.head!=NULL){
//both *this and P are non NULL
RESULT = new Complex_POLY();
*RESULT = *this;
Complex_POLY_CELL* temp;
temp = P.head;
s = -1.0*(temp->element);
RESULT->insert_nosort(s,temp->power);
while(temp->next!=NULL){
s = -1.0*(temp->next->element);
RESULT->insert_nosort(s,temp->next->power);
temp = temp->next;
}
return(*RESULT);
}
}
The next two operators involve + = and - = operations which must be handled differently than the usual + and - respectively. The main difference between this code and the stuff above is that the insertions are made into the this pointer that points to the left hand side. This kind of code shows up in fragments like
Complex_POLY S,R,P; //assume they have been built somehow R += P; S -= R;
// ************************************ //
// Overloaded Operator += //
// ************************************ //
Complex_POLY& Complex_POLY::operator+=(const Complex_POLY& P)
{
unsigned int p;
if(head==NULL && P.head==NULL){
//both this and the incoming polynomial are degenerate
//cout << "Both this and incoming polynomial are degenerate" << endl;
return(*this);
}
if(head!=NULL && P.head==NULL){
//we add nothing, so return *this
return(*this);
}
if(head==NULL && P.head!=NULL){
//*this is NULL, so return incoming P
*this = P;
return(*this);
}
if(head!=NULL && P.head!=NULL){
//both *this and P are non NULL
Complex_POLY_CELL* temp;
temp = P.head;
insert_nosort(temp->element,temp->power);
while(temp->next!=NULL){
insert_nosort(temp->next->element,temp->next->power);
temp = temp->next;
}
mergesort();
return(*this);
}
}
// ************************************ //
// Overloaded Operator -= //
// ************************************ //
Complex_POLY& Complex_POLY::operator-=(const Complex_POLY& P)
{
unsigned int p;
Complex_POLY *RESULT;
if(head==NULL && P.head==NULL){
//both this and the incoming polynomial are degenerate
RESULT = new Complex_POLY();
return(*RESULT);
}
if(head!=NULL && P.head==NULL){
//we subtract nothing, so return *this
return(*this);
}
if(head==NULL && P.head!=NULL){
//*this is NULL, so return -P
*RESULT = P;
Complex_POLY_CELL* temp;
temp = RESULT->head;
temp->element *= -1.0;
while(temp->next!=NULL){
temp->next->element *= -1.0;
temp = temp->next;
}
return(*RESULT);
}
if(head!=NULL && P.head!=NULL){
//both *this and P are non NULL
Complex_POLY_CELL* temp;
temp = P.head;
insert(-1.0*temp->element,temp->power);
while(temp->next!=NULL){
insert(-1.0*temp->next->element,temp->next->power);
temp = temp->next;
}
return(*this);
}
}
The next two methods involve the multiplication of polynomials. The distinction between the * and the * = is as discussed above. In the *, we create a PRODUCT polynomial to store the result and then return it, while in the * =, we store the result in the this pointer to the left hand side and return that.
This code implements what might be called brute force multiplication. Consider the mathematics: given polynomials P and Q with representations
| P(t) | = | ||
| Q(t) | = |
The product of P and Q is given as
| R(t) | = | ||
| Q(t) | = | ![]() ajbktn |
where the set {(j, k) : pj + qk = n} denotes the collection of (pj, qk) pairs which add up to a given power n. This set may be empty of course for some n, but this is a convenient notation. Note that this way of multiplying is of order P2 where P is the maximum of N and M, the degrees of the two polynomials. So this is not an efficient way to multiply polynomials for large degrees.
// ************************************ //
// Overloaded Operator * //
// ************************************ //
Complex_POLY Complex_POLY::operator*(const Complex_POLY& P)
{
//cout << "entering overloaded * for P+Q" << endl;
Complex_POLY* PRODUCT;
PRODUCT = new Complex_POLY();
if(head==NULL && P.head==NULL){
//both this and the incoming polynomial are degenerate
//cout << "Both this and incoming polynomial are degenerate" << endl;
return(*PRODUCT);
}
if(head!=NULL && P.head==NULL){
//we multiply nothing, so return NULL
return(*PRODUCT);
}
if(head==NULL && P.head!=NULL){
//*this is NULL, so return NULL
return(*PRODUCT);
}
if(head!=NULL && P.head!=NULL){
//both *this and P are non NULL
//
// *this = \sum_{j=0}^n a_j t^{p_j}
// P = \sum_{k=0}^m b_k t^{q_k}
// new polynomial = \sum_{n=0}^{p_n+q_m} c_n t^n
// where c_n = \sum_(j,k) a_j b_k such that p_j+q_k = n
//
//cout << "Both polys are non null so we start the mulitplication" << endl;
Complex_POLY_CELL* current = P.head;
Complex_POLY_CELL* temp = head;
while(temp!=NULL){
while(current!=NULL){
PRODUCT->insert_nosort(current->element*temp->element,
current->power + temp->power);
current = current->next;
}
current = P.head;
temp = temp->next;
}
PRODUCT->mergesort();
return(*PRODUCT);
}
}
// ************************************ //
// Overloaded Operator *= //
// ************************************ //
Complex_POLY& Complex_POLY::operator*=(const Complex_POLY& P)
{
Complex_POLY* PRODUCT;
PRODUCT = new Complex_POLY();
if(head==NULL && P.head==NULL){
//both this and the incoming polynomial are degenerate
return(*this);
}
else if(head!=NULL && P.head==NULL){
//we multiply nothing, so return NULL
return(*this);
}
else if(head==NULL && P.head!=NULL){
//*this is NULL, so return NULL
return(*this);
}
else{
//both *this and P are non NULL
Complex_POLY_CELL* current = P.head;
Complex_POLY_CELL* temp = head;
while(temp!=NULL){
while(current!=NULL){
PRODUCT->insert_nosort(current->element*temp->element,
current->power + temp->power);
current = current->next;
}
current = P.head;
temp = temp->next;
}
PRODUCT->mergesort();
*this = *PRODUCT;
return(*this);
}
}
This implements code to handle fragments of the sort
Complex_POLY S; Complex t = 3.3 + 4.4*I; //assume they have been built somehow R *= t;
// ********************************************* //
// Overloaded Operator * (Complex_POLY,Complex) //
// ********************************************* //
Complex_POLY operator*(Complex_POLY& P,Complex t)
{
Complex_POLY PRODUCT;
Complex_POLY_CELL *T;
if(P.head==NULL){
//the incoming polynomial is degenerate
return(PRODUCT);
}
else{
//P is non NULL
PRODUCT = P;
for(ComplexPOLYIter next(PRODUCT); next;++next){
*next() *= t;
}
return(PRODUCT);
}
}
// ************************************************ //
// Overloaded Operator * (Complex, Complex_POLY) //
// ************************************************ //
Complex_POLY operator*(Complex t,Complex_POLY& P)
{
Complex_POLY PRODUCT;
Complex_POLY_CELL *T;
if(P.head==NULL){
//the incoming polynomial is degenerate
return(PRODUCT);
}
else{
//P is non NULL
PRODUCT = P;
for(ComplexPOLYIter next(PRODUCT); next;++next){
*next() *= t;
}
return(PRODUCT);
}
}
// ********************************************** //
// Overloaded Operator *= (Complex,Complex_POLY) //
// ********************************************** //
Complex_POLY& operator*=(Complex_POLY& P,Complex t)
{
if(P.head==NULL){
//the incoming polynomial is degenerate
return(P);
}
else{
//P is non NULL
for(ComplexPOLYIter next(P); next;++next){
*next() *= t;
}
return(P);
}
}
\subsubsection{Evaluating a Polynomial:}
\small
\begin{verbatim}
// ***************************************** //
// Evaluation Function //
// ***************************************** //
Complex Complex_POLY::operator()(Complex x)
{
Complex value;
int i;
if(head==NULL){
//this polynomial is degenerate
value = 0.0;
return(value);
}
else{
//this is Non NULL
Complex value = 0.0;
Complex product = 1.0;
Complex_POLY_CELL* temp = head;
if(temp->next==NULL && temp->power==0){
value = temp->element;
return value;
}
if(temp->next==NULL && temp->power>0){
product = 1;
for(i=0;i<temp->power;++i)
product *= x;
return(product*temp->element);
}
value = temp->element;
while(temp->next!=NULL){
product = 1.0;
for(i=0;i<temp->power-temp->next->power;++i)
product *= x;
value = (temp->next->element+value*product);
temp = temp->next;
}
if(temp->power>0){
product = 1.0;
for(i = 0;i<temp->power;++i)
product *= x;
value *= product;
return value;
}
return(value);
}
}