 /*
##########################################################################
#                                                                        #
# 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 65 2005-05-17 12:03:09Z sbecuwe $

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

// ----
// extern FORTRAN-90 functions
// ----
extern "C" {
  void setround_(int&);
  void getexcept_(int&);
  void addf_(float&,float&,float&);
  void addd_(double&,double&,double&);
  void addl_(long double&,long double&,long double&);
  void mulf_(float&,float&,float&);
  void muld_(double&,double&,double&);
  void mull_(long double&,long double&,long double&);
  void divf_(float&,float&,float&);
  void divd_(double&,double&,double&);
  void divl_(long double&,long double&,long double&);
  void remf_(float&,float&,float&);
  void remd_(double&,double&,double&);
  void reml_(long double&,long double&,long double&);
  void sqrtf_(float&,float&);
  void sqrtd_(double&,double&);
  void sqrtl_(long double&,long double&);
  void rintegralf_(float&,float&);
  void rintegrald_(double&,double&);
  void rintegrall_(long double&,long double&);
  void rtls_(long double&,float&);
  void rtld_(long double&,double&);
  void rtds_(double&,float&);
  void cfs2d_(float&,double&);
  void cfs2q_(float&,long double&);
  void cfd2q_(double&, long double&);
  void rif_(float&,long int&);
  void rid_(double&,long int&);
  void ril_(long double&,long int&);
  void cif_(float&,long int&);
  void cid_(double&,long int&);
  void cil_(long double&,long int&);
  void ri64f_(float&, long long int&);
  void ri64d_(double&, long long int&);
  void ri64l_(long double&, long long int&);
  void ci64f_(float&,long long int&);
  void ci64d_(double&,long long int&);
  void ci64l_(long double&,long long int&);
  void b2df_(int&,float&,char&);
  void b2dd_(int&,double&,char&);
  void b2dl_(int&,long double&,char&);
  void d2bf_(float&,char&);
  void d2bd_(double&,char&);
  void d2bl_(long double&,char&);
}

// ----
// Includes
// ----
#include <cmath>
#include <cstdlib>
#include "DriverFloatRepr.h"
#include <sstream>
#include <string>

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();
      rtds_(dop1,fres);
      GetLibExceptions();
      DriverFloatRepr r(fres);
      return r;
    }
    else {
      double dres;
      // double naar double zinloze test
      dres = dop1;
      GetLibExceptions();
      DriverFloatRepr rd(dres);
      return rd;
    } 
  }
  else {
    long double lop1;
    lop1 = tolongdouble();

    if ((dsizeExp == 8) && (dsizeMant == 23) && dhidden) {
      SetLibEnvironment();
      rtls_(lop1,fres);
      GetLibExceptions();
      DriverFloatRepr r(fres);
      return r;
    }
    else if ((dsizeExp == 11) && (dsizeMant == 52) && dhidden) {
      double dres;
      SetLibEnvironment();
      rtld_(lop1,dres);
      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) {
    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;
      cfs2d_(op1,dres);
      GetLibExceptions();
      DriverFloatRepr rd(dres);
      return rd;
    }
    else {
      long double lres;
      cfs2q_(op1,lres);
      GetLibExceptions();
      DriverFloatRepr rl(lres);
      return rl;
    }
  } // if
  else if ((sizeExp == 11) && (sizeMant == 52) && hidden) {
    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;
      cfd2q_(dop1,lres);
      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) {
    float res,op1;
    op1= tofloat();
    SetLibEnvironment();
    rintegralf_(op1,res);
    GetLibExceptions();
    DriverFloatRepr r(res);
    return r;
  }
  else if ((sizeExp == 11) && (sizeMant == 52) && hidden) {
    double dres,dop1;
    dop1= todouble();
    SetLibEnvironment();
    rintegrald_(dop1,dres);
    GetLibExceptions();
    DriverFloatRepr rd(dres);
    return rd;
  }
  else {
    long double lres,lop1;
    lop1= tolongdouble();
    SetLibEnvironment();
    rintegrall_(lop1,lres);
    GetLibExceptions();
    DriverFloatRepr rl(lres);
    return rl;
  }
}

DriverFloatRepr DriverFloatRepr::ri(){
  long int res = 0;
  if ((sizeExp == 8) && (sizeMant == 23) && hidden) {
    float op1;
    op1 = tofloat();
    SetLibEnvironment();
    rif_(op1,res);
    GetLibExceptions();
  }
  else if ((sizeExp == 11) && (sizeMant == 52) && hidden) {
    double dop1;
    dop1 = todouble();
    SetLibEnvironment();
    rid_(dop1,res);
    GetLibExceptions();
  }
  else {
    long double lop1;
    lop1 = tolongdouble();
    SetLibEnvironment();
    ril_(lop1,res);
    GetLibExceptions();
  } 
  DriverFloatRepr r(res);
  return r;
}
DriverFloatRepr DriverFloatRepr::ru(){
  // Unsigned integers are not implemented in FORTRAN
  // but we need empty functionbody to be able to compile the testprogram
  return 0.0; // Because we have to return something
}

DriverFloatRepr DriverFloatRepr::rI(){
  long long int res;
  if ((sizeExp == 8) && (sizeMant == 23) && hidden) {
    float op1;
    op1= tofloat();
    SetLibEnvironment();
    ri64f_(op1,res);
    GetLibExceptions();
  }
  else if ((sizeExp == 11) && (sizeMant == 52) && hidden) {
    double dop1;
    dop1= todouble();
    SetLibEnvironment();
    ri64d_(dop1,res);
    GetLibExceptions();
  }
  else {
    long double lop1;
    lop1= tolongdouble();
    SetLibEnvironment();
    ri64l_(lop1,res);
    GetLibExceptions();
  }  
  DriverFloatRepr r(res);
  return r;
}

DriverFloatRepr DriverFloatRepr::rU(){
  // Unsigned integers are not implemented in FORTRAN
  // but we need empty functionbody to be able to compile the testprogram
  return 0.0;
}

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

DriverFloatRepr DriverFloatRepr::cu(int dsizeExp,int dsizeMant,int dhidden){
  // Unsigned integers are not implemented in FORTRAN
  // but we need empty functionbody to be able to compile the testprogram  
  return 0.0; // because we need to return something
}

DriverFloatRepr DriverFloatRepr:: cI(int dsizeExp,int dsizeMant,int dhidden){
  long long int op1;
  op1 = tolonglong();
  if ((dsizeExp == 8) && (dsizeMant == 23) && dhidden) {
    float fres;
    SetLibEnvironment();
    ci64f_(fres,op1);
    GetLibExceptions();
    DriverFloatRepr r(fres);
    return r;
  }
  else if ((dsizeExp == 11) && (dsizeMant == 52) && dhidden) {
    double dres;
    SetLibEnvironment();
    ci64d_(dres,op1);
    GetLibExceptions();
    DriverFloatRepr rd(dres);
    return rd;
  }
  else {
    long double lres;
    SetLibEnvironment();
    ci64l_(lres,op1);
    GetLibExceptions();
    DriverFloatRepr rl(lres);
    return rl;
  }  
}

DriverFloatRepr DriverFloatRepr:: cU(int dsizeExp,int dsizeMant,int dhidden){
  // Unsigned integers are not implemented in FORTRAN
  // but we need empty functionbody to be able to compile the testprogram
  return 0.0; // Because we need to return something 
}

DriverFloatRepr DriverFloatRepr:: b2d(int prec){
  unsigned int i,j;
  int r;
  static char buff[maxstr];
  string buffexp;
  ostringstream s;
  ostringstream e(buffexp);

  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();
    b2df_(prec,op1,*buff);
  }
  else if ((sizeExp == 11) && (sizeMant == 52) && hidden) {
    double op1;
    op1= todouble();
    
    SetLibEnvironment();
    b2dd_(prec,op1,*buff);
  }
  else {
    long double op1;
    op1= tolongdouble();
    
    SetLibEnvironment();
    b2dl_(prec,op1,*buff);
  }
  GetLibExceptions();
  
  i = 0;
  while ((buff[i] != '+') && (buff[i] != '-') && (buff[i] != '0')) i++;
  j = 0;
  if (buff[i] == '-') {
    res.decimal[j++] = '-';
    i += 3;
  }
  else if (buff[i] == '+') {
    res.decimal[j++] = '+';
    i += 3;
  }
  else {
    res.decimal[j++] = '+';
    i += 2;
  }
  r = i;
  for (; j <= prec; i++, j++)
    res.decimal[j] = buff[i];
  res.decimal[j++] = 'E';
  i++;
  if (buff[r] == '0')
    prec = 0; // detect zero
  r = atoi(&buff[i]); // exp to int
  r -= prec; // except if zero
  e << r << ends; // int to char
  if (r >= 0)
    res.decimal[j++] = '+';
  res.decimal[j] = '\0';
  strcat(res.decimal,e.str().c_str());
  
  return res;
}

DriverFloatRepr DriverFloatRepr:: b2d(unsigned prechlp){
  int prec=prechlp;
  unsigned int i,j;
  int r;
  static char buff[maxstr];
  string buffexp;
  ostringstream s;
  ostringstream e(buffexp);

  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();
    b2df_(prec,op1,*buff);
  }
  else if ((sizeExp == 11) && (sizeMant == 52) && hidden) {
    double op1;
    op1= todouble();
    
    SetLibEnvironment();
    b2dd_(prec,op1,*buff);
  }
  else {
    long double op1;
    op1= tolongdouble();
    
    SetLibEnvironment();
    b2dl_(prec,op1,*buff);
  }
  GetLibExceptions();
  
  i = 0;
  while ((buff[i] != '+') && (buff[i] != '-') && (buff[i] != '0')) i++;
  j = 0;
  if (buff[i] == '-') {
    res.decimal[j++] = '-';
    i += 3;
  }
  else if (buff[i] == '+') {
    res.decimal[j++] = '+';
    i += 3;
  }
  else {
    res.decimal[j++] = '+';
    i += 2;
  }
  r = i;
  for (; j <= prec; i++, j++)
    res.decimal[j] = buff[i];
  res.decimal[j++] = 'E';
  i++;
  if (buff[r] == '0')
    prec = 0; // detect zero
  r = atoi(&buff[i]); // exp to int
  r -= prec; // except if zero
  e << r << ends; // int to char
  if (r >= 0)
    res.decimal[j++] = '+';
  res.decimal[j] = '\0';
  strcat(res.decimal,e.str().c_str());
  
  return res;
}

DriverFloatRepr DriverFloatRepr::d2b() {
  int i;
  static char buff[256];
  
  for (i = 0;decimal[i] != '\0'; i++)
    buff[i] = decimal[i];
  
  while (i < 256)
    buff[i++] = ' ';
  
  if ((sizeExp == 8) && (sizeMant == 23) && hidden) {
    float r;
    SetLibEnvironment();
    d2bf_(r,*buff);
    GetLibExceptions();
    DriverFloatRepr res2(r);
    return res2;
  }
  else if ((sizeExp == 11) && (sizeMant == 52) && hidden) {
    double r;
    SetLibEnvironment();
    d2bd_(r,*buff);
    GetLibExceptions();
    DriverFloatRepr res1(r);
    return res1;
  }
  else {
    long double r;
    SetLibEnvironment();
    d2bl_(r,*buff);
    GetLibExceptions();
    DriverFloatRepr res(r);
    return res;
  } 
}
