 /*
##########################################################################
#                                                                        #
# Program: IeeeCC754                                                     #
#                                                                        #
# Description:                                                           #
#   IeeeCC754 or IEEE 754 Compliance Checker is a precision and range    #
#   independent tool to test whether an implementation of                #
#   floating-point arithmetic (in hardware or software) is compliant     #
#   with the principles of the IEEE 754-854 floating-point standards.    #
#   You can find out more about the testing tool IeeeCC754 at            #
#                                                                        #
#         http://www.win.ua.ac.be/~cant/ieeecc754.html                   #
#                                                                        #
#   This tool is in parts based on and greatly benefited from the        #
#   the program FPTEST developed by Jerome Coonen. For a full            #
#   description of the extensions to FPTEST and a reference to           #
#   the original Coonen program, please refer to the URL given above.    #
#   For the options available with the program IeeeCC754 and its         #
#   compatibility with David Hough's hexadecimal UCB format, we          #
#   also refer to the file readme.usage.                                 #
#                                                                        #
#  Usage: see readme.usage                                               #
#                                                                        #
#  Responsible authors:                                                  #
#         Brigitte Verdonk                                               #
#         Annie Cuyt                                                     #
#                                                                        #
#  Contributors:                                                         #
#         Tarun Agarwal (05-07/2002)                                     #
#         Stefan Becuwe (07/2000- )                                      #
#         Johan Bogo (10/1998-09/1999)                                   #
#         Wim Dausy (10/2002-09/2003)                                    #
#         Tim Gevers (10-12/2000)                                        #
#         Matthias Huesken (02/2004- )                                   #
#         Debby Ooms (10/1996-09/1997)                                   #
#         Geert Vermuyten (10/1996-09/1997)                              #
#         Dennis Verschaeren (09/1996-06/2000)                           #
#                                                                        #
#  Copyright (C) 2000,2001,2002,2003,2004,2005                           #
#                Universiteit Antwerpen                                  #
#                                                                        #
#  This program can be obtained from the authors, free, but WITHOUT ANY  #
#  WARRANTY; without even the implied warranty of MERCHANTABILITY or     #
#  FITNESS FOR A PARTICULAR PURPOSE.                                     #
#                                                                        #
#  Contact:                                                              #
#       Brigitte.Verdonk@ua.ac.be                                        #
#       Departement Wiskunde en Informatica                              #
#       Universiteit Antwerpen                                           #
#       Middelheimlaan 1                                                 #
#       B-2020 Antwerpen, Belgium                                        #
#                                                                        #
##########################################################################


$Id: BasicOptest.cc 65 2005-05-17 12:03:09Z sbecuwe $

                                                                     
 */
// ----
// Includes
// ----

#include <DriverFloatRepr.h>
#include <cmath>
#include <cstdlib>
#include <sstream>
#include <string>

// ----
// Extern C
// ----

extern "C" {
  float sqrtf(float);
  long double sqrtl(long double);
  float remainderf(float,float);
  long double remainderl(long double,long double);
}

DriverFloatRepr DriverFloatRepr::operator + (DriverFloatRepr& m) 
{ 
  if ((sizeExp == 8) && (sizeMant == 23) && hidden) {
    float res,op1,op2;

    op1= tofloat();
    op2= m.tofloat();

    SetLibEnvironment();
    res = op1 + op2;
    GetLibExceptions();
      
    DriverFloatRepr r(res);
    return r;
  }
  else if ((sizeExp == 11) && (sizeMant == 52) && hidden) {
    double dres,dop1,dop2;

    dop1= todouble();
    dop2= m.todouble();
    
    SetLibEnvironment();
    dres = dop1 + dop2;
    GetLibExceptions();
    
    DriverFloatRepr rd(dres);
    return rd;
  }
  else {
    long double lres,lop1,lop2;

    lop1= tolongdouble();
    lop2= m.tolongdouble();

    SetLibEnvironment();
    lres = lop1 + lop2;
    GetLibExceptions();
      
    DriverFloatRepr rl(lres);
    return rl;
  }
}

DriverFloatRepr DriverFloatRepr::operator - (DriverFloatRepr &m) {
  if ((sizeExp == 8) && (sizeMant == 23) && hidden) {
    float res,op1,op2;

    op1= tofloat();
    op2= m.tofloat();

    SetLibEnvironment();
    res = op1 - op2;
    GetLibExceptions();
    
    DriverFloatRepr r(res);
    return r;
  }
  else if ((sizeExp == 11) && (sizeMant == 52) && hidden) {
    double dres,dop1,dop2;

    dop1= todouble();
    dop2= m.todouble();

    SetLibEnvironment();
    dres = dop1 - dop2;
    GetLibExceptions();
    
    DriverFloatRepr rd(dres);
    return rd;
  }
  else {
    long double lres,lop1,lop2;

    lop1= tolongdouble();
    lop2= m.tolongdouble();

    SetLibEnvironment();
    lres = lop1 - lop2;
    GetLibExceptions();
    
    DriverFloatRepr rl(lres);
    return rl;
  }
}

DriverFloatRepr DriverFloatRepr::operator * (DriverFloatRepr &m) {
  if ((sizeExp == 8) && (sizeMant == 23) && hidden) {
    float res,op1,op2;

    op1= tofloat();
    op2= m.tofloat();

    SetLibEnvironment();
    res = op1 * op2;
    GetLibExceptions();
    
    DriverFloatRepr r(res);
    return r;
  }
  else if ((sizeExp == 11) && (sizeMant == 52) && hidden) {
    double dres,dop1,dop2;

    dop1= todouble();
    dop2= m.todouble();

    SetLibEnvironment();
    dres = dop1 * dop2;
    GetLibExceptions();
    
    DriverFloatRepr rd(dres);
    return rd;
  }
  else {
    long double lres,lop1,lop2;

    lop1= tolongdouble();
    lop2= m.tolongdouble();

    SetLibEnvironment();
    lres = lop1 * lop2;
    GetLibExceptions();
    
    DriverFloatRepr rl(lres);
    return rl;
  }
}

DriverFloatRepr DriverFloatRepr::operator / (DriverFloatRepr &m) {
  if ((sizeExp == 8) && (sizeMant == 23) && hidden) {
    float res,op1,op2;

    op1= tofloat();
    op2= m.tofloat();

    SetLibEnvironment();
    res = op1 / op2;
    GetLibExceptions();
    
    DriverFloatRepr r(res);
    return r;
  }
  else if ((sizeExp == 11) && (sizeMant == 52) && hidden) {
    double dres,dop1,dop2;

    dop1= todouble();
    dop2= m.todouble();

    SetLibEnvironment();
    dres = dop1 / dop2;
    GetLibExceptions();
    
    DriverFloatRepr rd(dres);
    return rd;
  }
  else {
    long double lres,lop1,lop2;

    lop1= tolongdouble();
    lop2= m.tolongdouble();

    SetLibEnvironment();
    lres = lop1 / lop2;
    GetLibExceptions();
    
    DriverFloatRepr rl(lres);
    return rl;
  }
}


DriverFloatRepr DriverFloatRepr::operator % (DriverFloatRepr &m) {
  if ((sizeExp == 8) && (sizeMant == 23) && hidden) {
    float res,op1,op2;

    op1= tofloat();
    op2= m.tofloat();

    SetLibEnvironment();
    asm volatile ("fprem1" : "=t" (res) : "0" (op1), "u" (op2));
    GetLibExceptions();
    
    DriverFloatRepr r(res);
    return r;
  }
  else if ((sizeExp == 11) && (sizeMant == 52) && hidden) {
    double dres,dop1,dop2;

    dop1= todouble();
    dop2= m.todouble();

    SetLibEnvironment();
    register double value;
    asm volatile
      ("1: fprem1\n\t"
       "fstsw  %%ax\n\t"
       "sahf\n\t"
       "jp     1b"
       : "=t" (value) : "0" (dop1), "u" (dop2) : "ax", "cc");
    dres = value;
    GetLibExceptions();
    
    DriverFloatRepr rd(dres);
    return rd;
  }
  else {
    long double lres,lop1,lop2;

    lop1= tolongdouble();
    lop2= m.tolongdouble();

    SetLibEnvironment();
    register long double value;
    asm volatile
      ("1: fprem1\n\t"
       "fstsw  %%ax\n\t"
       "sahf\n\t"
       "jp     1b"
       : "=t" (value) : "0" (lop1), "u" (lop2) : "ax", "cc");
    lres = value;
    GetLibExceptions();
    
    DriverFloatRepr rl(lres);
    return rl;
  }
}

DriverFloatRepr DriverFloatRepr::sqrt() {
  if ((sizeExp == 8) && (sizeMant == 23) && hidden) {
    float res,op1;

    op1= tofloat();

    SetLibEnvironment();
    asm volatile ("fsqrt" : "=t" (res) : "0" (op1));
    GetLibExceptions();
    
    DriverFloatRepr r(res);
    return r;
  }
  else if ((sizeExp == 11) && (sizeMant == 52) && hidden) {
    double dres,dop1;

    dop1= todouble();

    SetLibEnvironment();
    asm volatile ("fsqrt" : "=t" (dres) : "0" (dop1));
    GetLibExceptions();
    
    DriverFloatRepr rd(dres);
    return rd;
  }
  else {
    long double lres,lop1;
    lop1= tolongdouble();
    
    SetLibEnvironment();
    asm volatile ("fsqrt" : "=t" (lres) : "0" (lop1));
    GetLibExceptions();
    
    DriverFloatRepr rl(lres);
    return rl;
  }
}
