Purpose:

To let you demonstrate your ability to manipulate C integers by implementing floating-point addition with integer operations.

Assignment

Finish the program below that does floating point addition.

Cut and paste the following:

/*————————————————————————-*

*— —*

*— floatAdder.c —*

*— —*

*— This file adds 2 32-bit IEEE floating point numbers with —*

*— integer operations. Doesn’t handle ‘+inf’, ‘-inf’ or ‘NaN’ —*

*— properly, nor does it round properly. Those are the only 2 —*

*— bugs of which I’m aware. —*

*— —*

*— —- —- —- —- —- —- —- —- —*

*— —*

*— Version 1.0 2015 June 29 Joseph Phillips —*

*— —*

*————————————————————————-*/

#include

#include

//– Sign related constants –//

// PURPOSE: To tell how many bits to shift the sign bit from the least

// signficant position to where the sign bit belongs.

#define SIGN_SHIFT 31

// PURPOSE: To be the mask to only keep the sign bit.

#define SIGN_MASK (0x1 << SIGN_SHIFT)
// PURPOSE: To be the mask to keep everything but the sign bit.
#define EVERYTHING_BUT_SIGN_MASK (~SIGN_MASK)
//-- Exponent related constants --//
// PURPOSE: To tell how many bits to shift the exponent bit field from the
// least signficant position to where the exponent bit field belongs.
#define EXPONENT_SHIFT 23
// PURPOSE: To be the mask to only keep the exponent bit field.
#define EXPONENT_MASK ((unsigned)0xFF << EXPONENT_SHIFT)
// PURPOSE: To tell the exponent bit pattern for 'infinity' and
// 'not-a-number'.
#define EXPONENT_INFINITE_BIT_PATTERN 0xFF
// PURPOSE: To tell the exponent bit pattern for denormalized numbers
// (including 0.0).
#define EXPONENT_DENORMALIZED_BIT_PATTERN 0x00
// PURPOSE: To tell the 'bias' of the exponent bit field:
// (powerOf2) = (exponentBitPattern) - EXPONENT_BIAS
#define EXPONENT_BIAS 0x7F
// PURPOSE: To tell the power of 2 for 'infinity' and 'not-a-number'.
#define INFINITE_POWER_OF_2 +128
// PURPOSE: To tell the power of 2 for denormalized numbers (including 0.0):
#define DENORMALIZED_POWER_OF_2 -127
#define INDISTINGUISHABLE_FROM_0_POWER_OF_2 (DENORMALIZED_POWER_OF_2-23)
//-- Mantissa related constants --//
// PURPOSE: To tell the mask to only keep the mantissa bit field.
#define MANTISSA_MASK 0x007FFFFF
// PURPOSE: To tell give the hidden bit in its proper position.
#define MANTISSA_HIDDEN_BIT 0x00800000
// PURPOSE: To tell how many bits to shift the mantissa bit field from the
// least signficant position to where the mantissa bit field belongs.
#define MANTISSA_SHIFT 0
// PURPOSE: To tell how many mantissa bits there are (including hidden bit)
#define NUM_MANTISSA_BITS 24
//-- Miscellaneous related constants --//
// PURPOSE: To give the maximum length of C-strings.
#define TEXT_LEN 64
// PURPOSE: To return 1 if 'f' is 0.0 or -0.0. Returns 0 otherwise.
int isZero (float f)
{
unsigned int u = *(unsigned int*)&f;
// Your code here
return(0 /* Perhaps change this */);
}
// PURPOSE: To return the +1 if the sign of 'f' is positive, or -1 otherwise.
int getSign (float f)
{
unsigned int u = *(unsigned int*)&f;
// Your code here
return(0 /* Perhaps change this */);
}
// PURPOSE: To return the exponent (the X of 2^X) of the floating point
// 'f' from 'DENORMALIZED_POWER_OF_2' to 'INFINITE_POWER_OF_2'.
// (Does _not_ return the bit pattern.)
int getPowerOf2 (float f)
{
unsigned int u = *(unsigned int*)&f;
unsigned int i = 0; /* Perhaps change this */
// Your code here
return(0 /* Perhaps change this */);
}
// PURPOSE: To return the mantissa of 'f', with the HIDDEN_BIT or-ed in if
// 'f' is not denormalized.
unsigned int getMantissa (float f)
{
unsigned int mantissa = *(unsigned int*)&f;
// Your code here
return(0 /* Perhaps change this */);
}
// PURPOSE: To return the 0x0 when given +1, or 0x1 when given -1.
unsigned char signToSignBit (int sign)
{
// Your code here
return(0 /* Perhaps change this */);
}
// PURPOSE: To return the exponent field's bit pattern for power of 2
// 'powerOf2'. If 'powerOf2' is greater or equal to 'INFINITE_POWER_OF_2'
// then it returns 'EXPONENT_INFINITE_BIT_PATTERN'. If 'powerOf2' is
// less than or equal to 'DENORMALIZED_POWER_OF_2' then it
// returns 'EXPONENT_DENORMALIZED_BIT_PATTERN'. Otherwise it returns the
// corresponding bit pattern for 'powerOf2' given bias 'EXPONENT_BIAS'.
unsigned char pwrOf2ToExpBits (int powerOf2)
{
// Your code here
return(0 /* Perhaps change this */);
}
// PURPOSE: To return the mantissa _field_, 'mantissa' with its hidden
// bit turned off.
unsigned int mantissaField (unsigned int mantissa
)
{
// Your code here
return(0 /* Perhaps change this */);
}
// PURPOSE: To return the floating point number constructed from sign bit
// 'signBit'
float buildFloat (int sign,
int exp,
unsigned int mantissaBits
)
{
// Leave this code alone!
unsigned int u = (signToSignBit(sign) << SIGN_SHIFT) |
(pwrOf2ToExpBits(exp) << EXPONENT_SHIFT) |
(mantissaField(mantissaBits) << MANTISSA_SHIFT);
float f = *(float*)&u;
return(f);
}
// PURPOSE: To return 'f' added with 'g'.
float add (float f,
float g
)
{
// I. Handle when either 'f' or 'g' is 0.0:
if ( isZero(f) )
return(g);
if ( isZero(g) )
return(f);
// II. Do operation:
int signF = getSign(f);
int signG = getSign(g);
int powerOf2F = getPowerOf2(f);
int powerOf2G = getPowerOf2(g);
unsigned int mantissaF = getMantissa(f);
unsigned int mantissaG = getMantissa(g);
unsigned int mantissa;
int powerOf2;
int sign;
if (signF == signG)
{
// II.A. Do addition:
// (This is required.)
//
// See which has the bigger power-of-2: 'f' or 'g'
// Shift the smaller of the two by the difference in power of 2.
// Then add the mantissas.
//
// What is the value of 'powerOf2'? What is the value of 'sign'?
//
// How do you detect when the mantissa overflows?
// What do you do when the mantissa does overflow?
}
else
{
// II.B. Do subtraction:
// II.B.1. Handle canceling to 0:
if ( (powerOf2F == powerOf2G) && (mantissaF == mantissaG) )
return(buildFloat(+1,EXPONENT_DENORMALIZED_BIT_PATTERN,0x0));
// II.B.2. Do subtraction:
// (This is +5 extra credit.)
//
// Subtract the smaller from the bigger.
// How do you tell which is bigger from 'powerOf2F', 'powerOf2G', 'mantissaF' and 'mantissaG'?
// Do the same mantissa shifting as with addition.
//
// What is the value of 'powerOf2'? What is the value of 'sign'?
//
// With addition you may be left with too many bits in the mantissa,
// with subtraction you may be left with too few.
// If that's the case, then keeping shifting the most significant bit
// in the mantissa until either it gets to the mantissa's most
// significant bit position (the hidden bit's position) or until
// 'powerOf2' gets down to 'DENORMALIZED_POWER_OF_2'.
//
// Each time you shift 'mantissa' what should you do to 'powerOf2'?
}
// III. Return built float:
// Leave this code alone!
return(buildFloat(sign,powerOf2,mantissa));
}
// PURPOSE: To first test your 'getSign()', 'getPowerOf2()' and
// 'getMantissa()' functions, and then your 'add()' function. Ignores
// arguments from OS. Returns 'EXIT_SUCCESS' to OS.
int main ()
{
// Leave this code alone!
float f;
float g;
char text[TEXT_LEN];
do
{
printf("Please enter a floating point number or 0 to quit testing: ");
fgets(text,TEXT_LEN,stdin);
f = atof(text);
printf("The sign of %g is %+dn",f,getSign(f));
printf("The exponent of %g is 2^%dn",f,getPowerOf2(f));
printf("The mantissa of %g is 0x%06Xn",f,getMantissa(f));
}
while ( !isZero(f) );
printf("nn");
do
{
printf("Please enter the 1st floating point number to add: ");
fgets(text,TEXT_LEN,stdin);
f = atof(text);
printf("Please enter the 2nd floating point number to add: ");
fgets(text,TEXT_LEN,stdin);
g = atof(text);
printf(" You say %g + %g == %gn",f,g,add(f,g));
printf("The hardware says %g + %g == %gn",f,g,f+g);
}
while ( !isZero(f) && !isZero(g) );
return(EXIT_SUCCESS);
}
Finish the following functions:
What each should do is given in its comment.
isZero()
getSign()
getPowerOf2()
getMantissa()
signToSignBit()
pwrOf2ToExpBits()
mantissaField()
add()
Example output:
[instructor@JoesLaptopFedora16 Assign3]$ ./floatAdder
Please enter a floating point number or 0 to quit testing: 1
The sign of 1 is +1
The exponent of 1 is 2^0
The mantissa of 1 is 0x800000
Please enter a floating point number or 0 to quit testing: -1
The sign of -1 is -1
The exponent of -1 is 2^0
The mantissa of -1 is 0x800000
Please enter a floating point number or 0 to quit testing: 4
The sign of 4 is +1
The exponent of 4 is 2^2
The mantissa of 4 is 0x800000
Please enter a floating point number or 0 to quit testing: 6
The sign of 6 is +1
The exponent of 6 is 2^2
The mantissa of 6 is 0xC00000
Please enter a floating point number or 0 to quit testing: 7
The sign of 7 is +1
The exponent of 7 is 2^2
The mantissa of 7 is 0xE00000
Please enter a floating point number or 0 to quit testing: 7.5
The sign of 7.5 is +1
The exponent of 7.5 is 2^2
The mantissa of 7.5 is 0xF00000
Please enter a floating point number or 0 to quit testing: 7.75
The sign of 7.75 is +1
The exponent of 7.75 is 2^2
The mantissa of 7.75 is 0xF80000
Please enter a floating point number or 0 to quit testing: 7.875
The sign of 7.875 is +1
The exponent of 7.875 is 2^2
The mantissa of 7.875 is 0xFC0000
Please enter a floating point number or 0 to quit testing: 1
The sign of 1 is +1
The exponent of 1 is 2^0
The mantissa of 1 is 0x800000
Please enter a floating point number or 0 to quit testing: 2
The sign of 2 is +1
The exponent of 2 is 2^1
The mantissa of 2 is 0x800000
Please enter a floating point number or 0 to quit testing: 3
The sign of 3 is +1
The exponent of 3 is 2^1
The mantissa of 3 is 0xC00000
Please enter a floating point number or 0 to quit testing: 4
The sign of 4 is +1
The exponent of 4 is 2^2
The mantissa of 4 is 0x800000
Please enter a floating point number or 0 to quit testing: 5
The sign of 5 is +1
The exponent of 5 is 2^2
The mantissa of 5 is 0xA00000
Please enter a floating point number or 0 to quit testing: 1.4013e-45
The sign of 1.4013e-45 is +1
The exponent of 1.4013e-45 is 2^-127
The mantissa of 1.4013e-45 is 0x000001
Please enter a floating point number or 0 to quit testing: 1.7014115e+38
The sign of 1.70141e+38 is +1
The exponent of 1.70141e+38 is 2^126
The mantissa of 1.70141e+38 is 0xFFFFFD
Please enter a floating point number or 0 to quit testing: 1.7014117e+38
The sign of 1.70141e+38 is +1
The exponent of 1.70141e+38 is 2^126
The mantissa of 1.70141e+38 is 0xFFFFFF
Please enter a floating point number or 0 to quit testing: 1.7014118e+38
The sign of 1.70141e+38 is +1
The exponent of 1.70141e+38 is 2^127
The mantissa of 1.70141e+38 is 0x800000
Please enter a floating point number or 0 to quit testing: inf
The sign of inf is +1
The exponent of inf is 2^128
The mantissa of inf is 0x800000
Please enter a floating point number or 0 to quit testing: nan
The sign of nan is +1
The exponent of nan is 2^128
The mantissa of nan is 0xC00000
Please enter a floating point number or 0 to quit testing: -inf
The sign of -inf is -1
The exponent of -inf is 2^128
The mantissa of -inf is 0x800000
Please enter a floating point number or 0 to quit testing: 0
The sign of 0 is +1
The exponent of 0 is 2^-127
The mantissa of 0 is 0x000000
Please enter the 1st floating point number to add: 1
Please enter the 2nd floating point number to add: 2
You say 1 + 2 == 3
The hardware says 1 + 2 == 3
Please enter the 1st floating point number to add: 2
Please enter the 2nd floating point number to add: 3
You say 2 + 3 == 5
The hardware says 2 + 3 == 5
Please enter the 1st floating point number to add: 1.234
Please enter the 2nd floating point number to add: 4.321
You say 1.234 + 4.321 == 5.555
The hardware says 1.234 + 4.321 == 5.555
Please enter the 1st floating point number to add: -1
Please enter the 2nd floating point number to add: -.5
You say -1 + -0.5 == -1.5
The hardware says -1 + -0.5 == -1.5
Please enter the 1st floating point number to add: -2
Please enter the 2nd floating point number to add: -.5
You say -2 + -0.5 == -2.5
The hardware says -2 + -0.5 == -2.5
Please enter the 1st floating point number to add: -16
Please enter the 2nd floating point number to add: -0.125
You say -16 + -0.125 == -16.125
The hardware says -16 + -0.125 == -16.125
Please enter the 1st floating point number to add: -256
Please enter the 2nd floating point number to add: -0.125
You say -256 + -0.125 == -256.125
The hardware says -256 + -0.125 == -256.125
Please enter the 1st floating point number to add: -65536
Please enter the 2nd floating point number to add: -0.125
You say -65536 + -0.125 == -65536.1
The hardware says -65536 + -0.125 == -65536.1
Please enter the 1st floating point number to add: -1.4013e-45
Please enter the 2nd floating point number to add: -1.4013e-45
You say -1.4013e-45 + -1.4013e-45 == -2.8026e-45
The hardware says -1.4013e-45 + -1.4013e-45 == -2.8026e-45
Please enter the 1st floating point number to add: 131072
Please enter the 2nd floating point number to add: 0.03125
You say 131072 + 0.03125 == 131072
The hardware says 131072 + 0.03125 == 131072
Please enter the 1st floating point number to add: 1
Please enter the 2nd floating point number to add: -2
You say 1 + -2 == -1
The hardware says 1 + -2 == -1
Please enter the 1st floating point number to add: 3
Please enter the 2nd floating point number to add: -1
You say 3 + -1 == 2
The hardware says 3 + -1 == 2
Please enter the 1st floating point number to add: -4.25
Please enter the 2nd floating point number to add: 4
You say -4.25 + 4 == -0.25
The hardware says -4.25 + 4 == -0.25
Please enter the 1st floating point number to add: inf
Please enter the 2nd floating point number to add: 9
You say inf + 9 == inf
The hardware says inf + 9 == inf
Please enter the 1st floating point number to add: -inf
Please enter the 2nd floating point number to add: 9
You say -inf + 9 == -inf
The hardware says -inf + 9 == -inf
Please enter the 1st floating point number to add: 0
Please enter the 2nd floating point number to add: 9
You say 0 + 9 == 9
The hardware says 0 + 9 == 9
[instructor@JoesLaptopFedora16 Assign3]$