/// Primitive Compare Method
///
bool Variant::Equal(const Variant & rhs) const
{
    //std::cout << "variant equal: "<< *this << "==" << rhs << endl;
    //If they are both integers, make equality be exact.
    //If one is a float, make equality be with some tolerance.

    if(this->IsInteger()  && rhs.IsInteger())
        {
            return (this->GetInteger() == rhs.GetInteger());
        }
    else if (this->IsNumber() && rhs.IsNumber())
        {
            return (fabs(this->GetFloat() - rhs.GetFloat()) < .00000000001);
        }
    else if (this->IsString() && rhs.IsString())
        { //If both are strings, compare them

            //Get copies of the strings.
            std::string str1 = this->GetString();
            std::string str2 = rhs.GetString();

            //strcmp returns 0 if they are identical, a number otherwise
            bool b = (str1 == str2);
            return b;
        }
    else if (this->IsStackSignal() && rhs.IsStackSignal())
        {
            return (this->GetSignal() == rhs.GetSignal());
        }
    return false;
}
///This overloads the + operator for Variants.
///for strings, this concatenates them.
Variant Variant::operator +(const Variant & rhs) const
{
    pInt i;
    pDouble f;

    if(this->IsInteger()  && rhs.IsInteger())
        {
            i = this->GetInteger() + rhs.GetInteger();
            return Variant(i);
        }
    else if (this->IsNumber() && rhs.IsNumber())
        {
            f = this->GetFloat() + rhs.GetFloat();
            return Variant(f);
        }
    else if (this->IsString() || rhs.IsString())
        {
            std::string  tmp1, tmp2;
            tmp1 = GetString();
            tmp2 = rhs.GetString();
            tmp1 += tmp2;
            return Variant(tmp1);
        }
    else
        //There should be an error emmitted here
        i=0;
    return Variant(i);

}
///
/// Assignment Operator (overloaded)
Variant Variant::operator = (const Variant & value)
{

    //First, clean up 'this' if it contains data on free store
    // (e.g., a Variable or a string)
    free_mData();

    mDataType=value.GetDataType();
    switch(mDataType)
        {
        case P_DATA_NUMBER_INTEGER:  // an integer
            mData.iNumber = value.GetInteger();
            break;

        case P_DATA_NUMBER_FLOAT:    // a float
            mData.fNumber = value.GetFloat();
            break;

        case P_DATA_STRING:
            mData.String = strdup(value.GetString().c_str());
            break;

        case P_DATA_LOCALVARIABLE:        // a char* variable name
        case P_DATA_GLOBALVARIABLE:        // a char* variable name
            mData.Variable = strdup(value.GetVariableName().c_str());
            break;

        case P_DATA_FUNCTION:
            mData.Function = strdup(value.GetFunctionName().c_str());
            break;

        case P_DATA_FUNCTION_POINTER:
            mData.pFunction = value.GetFunctionPointer();
            break;

        case P_DATA_STACK_SIGNAL:
            mData.Signal = value.GetSignal();
            break;

        case P_DATA_COMPLEXDATA:
            {
            PComplexData * tmp = value.GetComplexData();
            //tmp is a pointer to complex data, which
            //is just a holder for the object.  We want to make a 
            //copy of tmp
            mComplexData = new PComplexData(*tmp);
            break;
            }
        case P_DATA_UNDEFINED: // undefined, error
        default:
            PError::SignalFatalError( "Undefined Variant type in Variant::operator = (Variant).");
            break;
        }
    return (*this);
}
///This overloads the * operator for Variants
Variant Variant::operator *(const Variant & rhs) const
{
    pInt i;
    pDouble f;

    if(this->IsInteger()  && rhs.IsInteger())
        {
            i = this->GetInteger() * rhs.GetInteger();
            return Variant(i);
        }
    else if (this->IsNumber() && rhs.IsNumber())
        {

            f = this->GetFloat() * rhs.GetFloat();
            return Variant(f);
        }
    else
        i=0;
    return Variant(i);

}
Variant::Variant(const Variant &v):
    mComplexData(NULL)
{

    
    //This should behave differently depending on what type of variant v is
    mDataType = v.GetDataType();

    switch(mDataType)
        {

        case P_DATA_NUMBER_INTEGER:  // an integer
            mData.iNumber = v.GetInteger();
            break;

        case P_DATA_NUMBER_FLOAT:    // a float
            mData.fNumber = v.GetFloat();
            break;

        case P_DATA_STRING:
            //            cout << "testing case string:<" << v << ">"<<endl;
            mData.String = strdup(v.GetString().c_str());
            break;

        case P_DATA_LOCALVARIABLE:        // a variable name
        case P_DATA_GLOBALVARIABLE:        // a variable name
            mData.Variable = strdup(v.GetVariableName().c_str());
            break;

        case P_DATA_FUNCTION:
            //Memory problem here, diagnosed by efence:
            mData.Function = strdup(v.GetFunctionName().c_str());
            break;

        case P_DATA_FUNCTION_POINTER:
            mData.pFunction = v.GetFunctionPointer();
            break;


        case P_DATA_STACK_SIGNAL:
            mData.Signal = v.GetSignal();
            break;

            //This needs to  make a deep copy

        case P_DATA_COMPLEXDATA:
            {

                //cout<<"TYPE:" << v << endl;
                PComplexData * pcd = v.GetComplexData();

                if(pcd)
                    mComplexData  = new PComplexData(*pcd);
                else 
                    mComplexData = NULL;

            }
            break;

        case P_DATA_UNDEFINED: // undefined, not an error
            break;
        default:

            cerr << "Undefined Data Type in Variant copy constructor. Type: " << mDataType << endl;
            cerr << v << endl;
            PError::SignalFatalError("Undefined Data Type.");
        break;

        }

}