Due: Friday October 2 at 11:59pm
For this assignment you will be writing bit manipulation functions. Your functions will need to perform the same as the standard operations. Testing code will be provided. After writing the specified functions, you will submit them via the department's Git server.
#include <iostream> #include <iomanip> #include <cstdint> #include <cmath> #include <functional> #include <string> union Bits { float f; uint32_t u; int32_t i; }; void printBits(float in); void printBits(int32_t in); float absFloatBitwise(float in); int32_t absIntBitwise(int32_t in); float negateFloatBitwise(float in); int32_t negateIntBitwise(int32_t in); float doubleFloatBitwise(float in); int32_t doubleIntBitwise(int32_t in); void testFloat(std::string name, std::function<float(float)> standardFunction, std::function<float(float)> bitwiseFunction); void testInt(std::string name, std::function<int(int)> standardFunction, std::function<int(int)> bitwiseFunction); void printBits(float in) { Bits b; b.f = in; // Store the current format status of std::out std::ios state(nullptr); state.copyfmt(std::cout); std::cout << b.f << " = 0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << b.u << "\n"; uint32_t sign = ????; uint32_t exponent = ????; int32_t unbiased_exponent = int32_t(exponent) - 127; uint32_t mantissa = ????; std::cout << "Sign: 0x" << std::hex << sign << " " << "Exponent: 0x" << std::hex << std::setfill('0') << std::setw(2) << exponent << " Unbiased: " << std::dec << unbiased_exponent << " " << "Mantissa: 0x" << std::hex << std::setfill('0') << std::setw(6) << mantissa << " "; if (exponent == 0xFF) { std::cout << "Special value: "; if (mantissa == 0) { if (sign == 0) std::cout << "positive infinity"; else std::cout << "negative infinity"; } else { std::cout << "NaN"; } } else if (exponent == 0) { std::cout << "Denormalized "; if (sign == 0) std::cout << "positive"; else std::cout << "negative"; } else { std::cout << "Normalized "; if (sign == 0) std::cout << "positive"; else std::cout << "negative"; } std::cout << "\n"; // Restore the format status of std::out std::cout.copyfmt(state); } void printBits(int32_t in) { Bits b; b.i = in; // Store the current format status of std::out std::ios state(nullptr); state.copyfmt(std::cout); std::cout << std::dec << b.i << " = 0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << b.u << " "; uint32_t sign = ????; if (sign == 0) std::cout << "positive\n"; else std::cout << "negative\n"; // Restore the format status of std::out std::cout.copyfmt(state); } void testFloat(std::string name, std::function<float(float)> standardFunction, std::function<float(float)> bitwiseFunction) { std::cout << "Testing " << name << std::endl; for (uint64_t i = 0; i < (uint64_t{1} << 33); ++i) { Bits original; original.u = uint32_t(i); Bits normal; normal.f = standardFunction(original.f); Bits bits; bits.f = bitwiseFunction(original.f); if (normal.u != bits.u) { std::cout << "\nFound difference for i = " << std::dec << i << " = 0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << i << ":\n" << "Original:\n"; printBits(original.f); std::cout << "Bitwise calculated:\n"; printBits(bits.f); std::cout << "std::abs calculated:\n"; printBits(normal.f); } } } void testInt(std::string name, std::function<int(int)> standardFunction, std::function<int(int)> bitwiseFunction) { std::cout << "Testing " << name << std::endl; for (uint64_t i = 0; i < (uint64_t{1} << 33); ++i) { Bits original; original.u = uint32_t(i); Bits normal; normal.i = standardFunction(original.i); Bits bits; bits.i = bitwiseFunction(original.i); if (normal.u != bits.u) { std::cout << "\nFound difference for i = " << std::dec << i << " = 0x" << std::uppercase << std::hex << std::setfill('0') << std::setw(8) << i << ":\n" << "Original:\n"; printBits(original.i); std::cout << "Bitwise calculated:\n"; printBits(bits.i); std::cout << "Standard calculated:\n"; printBits(normal.i); } } } int main() { testFloat("float absolute value", [](float a){ return std::abs(a); }, absFloatBitwise); testInt("int absolute value", [](int a){ return std::abs(a); }, absIntBitwise); testFloat("float negate", [](float a){ return -a; }, negateFloatBitwise); testInt("int negate", [](int a){ return -a; }, negateIntBitwise); testFloat("float double", [](float a){ return 2 * a; }, doubleFloatBitwise); testInt("int double", [](int a){ return 2 * a; }, doubleIntBitwise); return 0; }
There are six functions to write. When writing them you are restricted on the operations you can use to ensure you use bit level manipulations (and, or, not, xor, left shift, right shift). Before worry about these restrictions try to write the function using only bit operations and you will likely come up with solutions that meet the restrictions.
When complete and correct, the starting code should output:
Testing float absolute value Testing int absolute value Testing float negate Testing int negate Testing float double Testing int doubleThis took 3.5 minutes on my laptop and 7 minutes on the Linux servers, so the total program you write could easily take as long. As you are working, I recommend you comment out the appropriate test function calls in main as you are working, so you only have one test uncommented at a time while you work on each function.
Your work must be submitted via the department's Git server. To do so, perform the following steps: