 /*
##########################################################################
#                                                                        #
# 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: Conversiontest.cc 78 2005-11-02 20:14:19Z huesken $

                                                                     
 */
/**     \file
 *      \brief Specific definitions of Class DriverFloatRepr for SunSparc_c++ conversions
 */

// ----
// Includes
// ----

#include <Types.h>
#include <DriverFloatRepr.h>
#include <cmath>
#include <cstdlib>
#include <sstream>
#include <string>
using namespace std;

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

extern "C" {
  float r_rint_(float &);
  long double rintl(long double);
  int irintf(float);
  int irint(double);
  int irintl(long double);
}

DriverFloatRepr DriverFloatRepr::roundto(int dsizeExp, int dsizeMant, int dhidden) {
  float fres;
  if ((sizeExp == 8) && (sizeMant == 23) && hidden) {
    float op1;
    op1 = tofloat();
    SetLibEnvironment();
    fres = op1;
    GetLibExceptions();
    DriverFloatRepr r(fres);
    return r;
  }
  else if ((sizeExp == 11) && (sizeMant == 52) && hidden) {
    double dop1;
    dop1 = todouble();
    if ((dsizeExp == 8) && (dsizeMant == 23) && dhidden) {
      SetLibEnvironment();
      fres = dop1;
      GetLibExceptions();
      DriverFloatRepr r(fres);
      return r;
    }
    else {
      double dres;
      dres = dop1;
      GetLibExceptions();
      DriverFloatRepr rd(dres);
      return rd;
    }
  }
  else {
    long double lop1;
    lop1 = tolongdouble();

    if ((dsizeExp == 8) && (dsizeMant == 23) && dhidden) {
      SetLibEnvironment();
      fres = lop1;
      GetLibExceptions();
      DriverFloatRepr r(fres);
      return r;
    }
    else if ((dsizeExp == 11) && (dsizeMant == 52) && dhidden) {
      double dres;
      SetLibEnvironment();
      dres = lop1;
      GetLibExceptions();
      DriverFloatRepr rd(dres);
      return rd;
    }
    else {
      long double lres;
      SetLibEnvironment();
      lres = lop1;
      GetLibExceptions();
      DriverFloatRepr rl(lres);
      return rl;
    }
  } // else
}

DriverFloatRepr DriverFloatRepr::copyto(int dsizeExp, int dsizeMant, int dhidden) {
  if ((sizeExp == 8) && (sizeMant == 23) && hidden) {   //SunSparc float
    float op1;
    op1 = tofloat();

    SetLibEnvironment();

    if ((dsizeExp == 8) && (dsizeMant == 23) && dhidden) {
      float fres;
      fres = op1;
      GetLibExceptions();
      DriverFloatRepr r(fres);
      return r;
    }
    else if ((dsizeExp == 11) && (dsizeMant == 52) && dhidden) {
      double dres;
      dres = op1;
      GetLibExceptions();
      DriverFloatRepr rd(dres);
      return rd;
    }
    else {
      long double lres;
      lres = op1;
      GetLibExceptions();
      DriverFloatRepr rl(lres);
      return rl;
    }
  } // if
  else if ((sizeExp == 11) && (sizeMant == 52) && hidden) { //SunSparc double
    double dop1;
    dop1 = todouble();

    SetLibEnvironment();
    
    if ((dsizeExp == 11) && (dsizeMant == 52) && dhidden) {
      double dres;
      dres = dop1;
      GetLibExceptions();
      DriverFloatRepr rd(dres);
      return rd;
    }
    else {
      long double lres;
      lres = dop1;
      GetLibExceptions();
      DriverFloatRepr rl(lres);
      return rl;
    }

  }
  else {
    long double lop1, lres;
    lop1 = tolongdouble();

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

//???
DriverFloatRepr DriverFloatRepr::rint() {
  if ((sizeExp == 8) && (sizeMant == 23) && hidden) {   //SunSparc float
    float res, op1;
    op1 = tofloat();

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

    SetLibEnvironment();

    dres =::rint(dop1);
    GetLibExceptions();
    DriverFloatRepr rd(dres);
    return rd;
  }
  else {    //long double
    long double lres, lop1;
    lop1 = tolongdouble();
    SetLibEnvironment();
    lres = rintl(lop1);
    GetLibExceptions();
    DriverFloatRepr rl(lres);
    return rl;
  }
}

//roundto long int (SunSparc 32bit)
DriverFloatRepr DriverFloatRepr::ri() {
  long32 res = 0;
  if ((sizeExp == 8) && (sizeMant == 23) && hidden) {   //SunSparc float
    float op1;
    op1 = tofloat();
    SetLibEnvironment();
    res = irintf(op1);
    GetLibExceptions();
  }
  else if ((sizeExp == 11) && (sizeMant == 52) && hidden) { //SunSparc double
    double dop1;
    dop1 = todouble();
    SetLibEnvironment();
    res = irint(dop1);
    GetLibExceptions();
  }
  else {    //long double
    long double lop1;
    lop1 = tolongdouble();
    SetLibEnvironment();
    res = irintl(lop1);
    GetLibExceptions();
  }

  DriverFloatRepr r(res);

  return r;
}

//roundto unsigned long (SunSparc 32bit)
DriverFloatRepr  DriverFloatRepr::ru() {
  ulong32 res;
  if ((sizeExp == 8) && (sizeMant == 23) && hidden) {   //SunSparc float
    float op1;
    op1= tofloat();
    SetLibEnvironment();
    res = (unsigned int) op1;
    GetLibExceptions();
  }
  else if ((sizeExp == 11) && (sizeMant == 52) && hidden) { //Sunsparc double
    double dop1;
    dop1= todouble();
    SetLibEnvironment();
    res = (unsigned int) dop1;
    GetLibExceptions();  
  }
  else {    //long double
    long double lop1;
    lop1= tolongdouble();
    SetLibEnvironment();
    res = (unsigned int) lop1;
    GetLibExceptions();
  } 
  DriverFloatRepr r(res);
  return r;
}

//roundto long long (SunSparc 64bit)
DriverFloatRepr DriverFloatRepr::rI() {
  long long res;
  if ((sizeExp == 8) && (sizeMant == 23) && hidden) {   //SunSparc float
    float op1;
    op1= tofloat();
    SetLibEnvironment();
    res = (long long)op1;
    GetLibExceptions();
  }
  else if ((sizeExp == 11) && (sizeMant == 52) && hidden) { //SunSparc double
    double dop1;
    dop1= todouble();
    SetLibEnvironment();
    res = (long long)dop1; 
    GetLibExceptions(); 
  }
  else {    //long double
    long double lop1;
    lop1= tolongdouble();
    SetLibEnvironment();
    res = (long long)lop1;
    GetLibExceptions();
  }  
  DriverFloatRepr r(res);
  return r;
}

//roundto unsigned long long int (Sunsparc 64bit)
DriverFloatRepr  DriverFloatRepr::rU() {
  unsigned long long int res;
  if ((sizeExp == 8) && (sizeMant == 23) && hidden) {   //SunSparc float
    float op1;
    op1= tofloat();
    SetLibEnvironment();
    res = (unsigned long long int)op1;
    GetLibExceptions();
  }
  else if ((sizeExp == 11) && (sizeMant == 52) && hidden) { //SunSparc double
    double dop1;
    dop1= todouble();
    SetLibEnvironment();
    res = (unsigned long long int)dop1; 
    GetLibExceptions(); 
  }
  else {    //long double
    long double lop1;
    lop1= tolongdouble();
    SetLibEnvironment();
    res = (unsigned long long int)lop1;
    GetLibExceptions();
  }
  DriverFloatRepr r(res);
  return r;
}

//cast to int
DriverFloatRepr  DriverFloatRepr::ci(int dsizeExp,int dsizeMant,int dhidden) {
  int op1;
  op1 = toint();
  if ((dsizeExp == 8) && (dsizeMant == 23) && dhidden) {    //SunSparc float
    float fres; 
    SetLibEnvironment();
    fres = (float) op1; 
    GetLibExceptions();  
    DriverFloatRepr r(fres);
    return r;
  }
  else if ((dsizeExp == 11) && (dsizeMant == 52) && dhidden) {  //SunSparc double
    double dres;
    SetLibEnvironment();
    dres = (double) op1;
    GetLibExceptions();  
    DriverFloatRepr rd(dres);
    return rd;  
  }
  else {    //long double
    long double lres;
    SetLibEnvironment();
    lres = (long double) op1; 
    GetLibExceptions();  
    DriverFloatRepr rl(lres);
    return rl;
  }
}

//cast to unsigned int
DriverFloatRepr  DriverFloatRepr::cu(int dsizeExp,int dsizeMant,int dhidden) {
  unsigned int op1;
  op1 = touint();
  if ((dsizeExp == 8) && (dsizeMant == 23) && dhidden) {    //SunSparc float
    float fres;
    SetLibEnvironment();
    fres = (float) op1; 
    GetLibExceptions();  
    DriverFloatRepr r(fres);
    return r;
  }
  else if ((dsizeExp == 11) && (dsizeMant == 52) && dhidden) {  //SunSparc double
    double dres;
    SetLibEnvironment();
    dres = (double) op1; 
    GetLibExceptions();  
    DriverFloatRepr rd(dres);
    return rd;  
  }
  else {    //long double
    long double lres;
    SetLibEnvironment();
    lres = (long double) op1; 
    GetLibExceptions();  
    DriverFloatRepr rl(lres);
    return rl;
  }
}

//cast to long long int (SunSparc 64bit)
DriverFloatRepr  DriverFloatRepr::cI(int dsizeExp,int dsizeMant,int dhidden) {
  long long int op1;
  op1 = tolonglong();
  if ((dsizeExp == 8) && (dsizeMant == 23) && dhidden) {    //SunSparc float
    float fres; 

    SetLibEnvironment();

    fres = (float) op1; 
    GetLibExceptions();  
    DriverFloatRepr r(fres);
    return r;
  }
  else if ((dsizeExp == 11) && (dsizeMant == 52) && dhidden) {  //SunSparc double
    double dres;

    SetLibEnvironment();

    dres = (double) op1; 
    GetLibExceptions();  
    DriverFloatRepr rd(dres);
    return rd;  
  }
  else {    //long double
    long double lres;

    SetLibEnvironment();

    lres = (long double) op1; 
    GetLibExceptions();  
    DriverFloatRepr rl(lres);
    return rl;
  }
}

//cast to unsigned long long int (SunSparc 64bit)
DriverFloatRepr  DriverFloatRepr::cU(int dsizeExp,int dsizeMant,int dhidden) {
  unsigned long long int op1;
  op1 = toulonglong();
  if ((dsizeExp == 8) && (dsizeMant == 23) && dhidden) {    //SunSparc float
    float fres; 
    SetLibEnvironment();

    fres = (float) op1; 
    GetLibExceptions();  
    DriverFloatRepr r(fres);
    return r;
  }
  else if ((dsizeExp == 11) && (dsizeMant == 52) && dhidden) {  //SunSparc double
    double dres;

    SetLibEnvironment();

    dres = (double) op1; 
    GetLibExceptions();  
    DriverFloatRepr rd(dres);
    return rd;  
  }
  else {    //long double
    long double lres;

    SetLibEnvironment();

    lres = (long double) op1; 
    GetLibExceptions();  
    DriverFloatRepr rl(lres);
    return rl;
  }
}

DriverFloatRepr DriverFloatRepr::b2d(int prec) {
  unsigned int i, j;
  string buffexp;
  int bufndx;
  ostringstream s;
  ostringstream e(buffexp);

  if (prec > 1) {
    s.setf(ios::scientific, ios::floatfield);
    s.precision(prec-1); // adjust number of digits
  }
  else {
    s.setf(ios::scientific, ios::floatfield);
    s.setf(ios::showpoint, ios::floatfield);
    s.precision(prec); // adjust number of digits
  }
  e.setf(ios::fixed, ios::floatfield);

  DriverFloatRepr res;
  // only create new string if there isn't already one
  if (res.decimal == NULL)
  res.decimal = new char[maxstr];
  
  if ((sizeExp == 8) && (sizeMant == 23) && hidden) {
    float op1;
    op1= tofloat();
    SetLibEnvironment();
    s << op1 << ends;
  }
  else if ((sizeExp == 11) && (sizeMant == 52) && hidden) {
    double op1;
    op1= todouble();
    SetLibEnvironment();
    s << op1 << ends;
  }
  else {
    long double op1;
    op1= tolongdouble();
    SetLibEnvironment();
    s << op1 << ends;
  }
  GetLibExceptions();

  const string buff = s.str();
  if (buff[0] == '-') {
    res.decimal[0] = '-';
    bufndx = 1;
  } else {
    res.decimal[0] = '+';
    bufndx = 0;
  }

  if (buff[bufndx] != '0') {
    res.decimal[1] = buff[bufndx];
  
    if (buff[bufndx+1] != '\0') {
      i = 2;
  for (;(int)i <= prec; i++)
	res.decimal[i] = buff[i+bufndx];
      j = i-1+bufndx;
  
  while (buff[j++] != 'e');
  res.decimal[i++] = 'E';

  int r = atoi(&buff[j]); // exp to int
  r -= prec - 1;
  e << r << ends; // int to char
  
  if (r >= 0)
    res.decimal[i++] = '+';
  res.decimal[i] = '\0';
  
  strcat(res.decimal,e.str().c_str());
      }
    }
  else if ((buff[bufndx+1] == '.') && (buff[bufndx+2] != '0')) {
    res.decimal[1] = buff[bufndx+2];
      res.decimal[2] = 'E';
      res.decimal[3] = '-';
      res.decimal[4] = '1';
      res.decimal[5] = '\0';
    }
    else {
      res.decimal[1] = '0';
      res.decimal[2] = 'E';
      res.decimal[3] = '+';
      res.decimal[4] = '0';
      res.decimal[5] = '\0';
    }

  return res;
  }
  
  
DriverFloatRepr DriverFloatRepr::b2d(unsigned prec) {
  
  return DriverFloatRepr::b2d((int)prec);
  
      }
  

DriverFloatRepr  DriverFloatRepr::d2b() {
  istringstream s(decimal);
  
  if ((sizeExp == 8) && (sizeMant == 23) && hidden) {
    float r=0;
    SetLibEnvironment();
    s >> r;
    GetLibExceptions();
    DriverFloatRepr res2(r);
    return res2;
  }
  else if ((sizeExp == 11) && (sizeMant == 52) && hidden) {
    double r=0;
    SetLibEnvironment();
    s >> r;
    GetLibExceptions();
    DriverFloatRepr res1(r);
    return res1;
  }
  else {
    long double r=0;
    SetLibEnvironment();
    s >> r;
    GetLibExceptions();
    DriverFloatRepr res(r);
    return res;
  }
}
