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

                                                                     
*/

#include <cmath>
#include <Types.h>
#include <DriverFloatRepr.h>

/* 
By default, all functions in this file are declared in the header file

  DriverFloatRepr.h

except for two functions 

DriverFloatRepr::DriverFloatRepr(<MyDatatype &D>)
<MyDatatype> DriverFloatRepr::to()

These two functions, for conversion between the floating-point
data type of your target implementation and DriverFloatRepr, the
floating-point data type of the driver program, should be declared
explicitly in the header file DriverFloatRepr.h, with MyDatatype
replaced by the appropriate identifier.  */

void DriverFloatRepr::SetLibRound()
{
  /* Make your library calls for changing the rounding mode */
  
  switch (GetFPRound())
    { case RM_NEAR:
      // change rounding mode to round to nearest break; 
      case RM_ZERO:
      // change rounding mode to round to zero break; 
      case RM_UP:
      // change rounding mode to round up break;
      case RM_DOWN:
      // change rounding mode to round down break; 
    } 
}

void DriverFloatRepr::SetLibEnvironment()
{
  // clear all floating-point exceptions
}

void DriverFloatRepr::GetLibExceptions()
{
  // check for raised exceptions
  if <test divide by zero>
    SetFPDivByZero();
  if <test invalid>
    SetFPInvalid();
  if <test underflow>
    SetFPUnderflow();
  if <test overflow>
    SetFPOverflow();
  if <test inexact>
    SetFPInexact();
}

DriverFloatRepr::DriverFloatRepr(<MyDatatype &D>) { 
  // convert your floating-point data type to the floating-point
  // representation of the driver program
  // replace MyDatatype by the appropriate identifier
  sizeExp = <your exponent size>;
  sizeMant = <your precision>;
  mant = Bitstring(sizeMant);
  exp = Bitstring(sizeExp);
  unsigned int i;
  if <check sign == minus>
    sign = 1;
  else
    sign = 0;
  // convert exponent
  for (i = sizeExp - 1;i >= 0; i--) {
    if (fmod(<your exponent>,2) != 0)
      exp.PutBit(i,1);
    <your exponent> /= 2;
  }
  // convert mantissa
  for (i = 0;i < sizeMant; i++)
    mant.PutBit(i,<your bit at position i>);
}

<MyDatatype> DriverFloatRepr::to()
  // convert the the floating-point representation of the driver program
  // to the floating-point data type of your implementation
{
  unsigned int i;
  if (sign == 0)
    <set sign = plus>
  else {
    <minus>
  }
  for (i = 0;i < sizeExp; i++) {
    if (exp.GetBit(i) == 1)
      <set exponent bit at pos i>
  } 
  for (i = 0;i < sizeMant; i++)
     <set mantissa bit at position i = mant.GetBit(i)>;
}

// conversions between DriverFloatRepr and hardware integer
// data types; implementation should not be modified !
// --

DriverFloatRepr::DriverFloatRepr(long32 i) {
  Bitstring temp(32);
  hidden = 0;
  sizeMant = 32;
  sizeExp = 0;
  temp[0] = (ulong32) i;
  temp.SubBitstring(0,mant);
}

DriverFloatRepr::DriverFloatRepr(ulong32 i) {
  Bitstring temp(32);
  hidden = 0;
  sizeMant = 32;
  sizeExp = 0;
  temp[0] = (ulong32) i;
  temp.SubBitstring(0,mant);
}

DriverFloatRepr::DriverFloatRepr(long long i) {
  ulong32 * tmparray;
  tmparray = (ulong32 *)&i;
  Bitstring temp(64);
  if (Endian == MYLITTLE_ENDIAN)
    {
      temp[0] = tmparray[0];
      temp[1] = tmparray[1];
    }
  else 
    {
      temp[0] = tmparray[1];
      temp[1] = tmparray[0];
    }
  hidden = 0;
  sizeMant = 64;
  sizeExp = 0;
  temp.SubBitstring(0,mant);
}

DriverFloatRepr::DriverFloatRepr(unsigned long long i) {
  ulong32 * tmparray;
  tmparray = (ulong32 *)&i;
  Bitstring temp(64);
  if (Endian == MYLITTLE_ENDIAN)
    {
      temp[0] = tmparray[0];
      temp[1] = tmparray[1];
    }
  else 
    {
      temp[0] = tmparray[1];
      temp[1] = tmparray[0];
    }
  hidden = 0;
  sizeMant = 64;
  sizeExp = 0;
  temp.SubBitstring(0,mant);
}

int DriverFloatRepr::toint() {
  return *((int *)(&mant[0]));
}

unsigned int DriverFloatRepr::touint() {
  return ((unsigned int *)(&mant[0]));
}

long long int DriverFloatRepr::tolonglong() {
  ulong32 tmparray[2];

  if (Endian == MYLITTLE_ENDIAN)
    {
      tmparray[0] = mant[0];
      tmparray[1] = mant[1];
    }
  else 
    {
      tmparray[0] = mant[1];
      tmparray[1] = mant[0];
    }
  return *((long long int *)tmparray);
}

unsigned long long int DriverFloatRepr::toulonglong() {
  ulong32 tmparray[2];
  if (Endian == MYLITTLE_ENDIAN)
    {
      tmparray[0] = mant[0];
      tmparray[1] = mant[1];
    }
  else 
    {
      tmparray[0] = mant[1];
      tmparray[1] = mant[0];
    }
  return *((unsigned long long int *)tmparray);
} 

