/**************************************************************************** * Copyright: * Copyright (c) 2019 by Douglas Wilhelm Harder. All rights reserved. * * Disclaimer: * This source code is provided for the ECE 204 Numerical Methods course * taught at the University of Waterloo. The material in it reflects the * author’s best judgment in light of the information available to that * individual at the time of preparation. Any reliance on this source code * by any party for any other purpose are the responsibility of such * parties. The authors accept no responsibility for damages, if any, * suffered by any party as a result of decisions made or actions based * on these course slides for any other purpose than that for which it * was intended. * * No warranty * The software is provided "as is", without warranty of any kind, express * or implied, including but not limited to the warranties of merchant- * ability, fitness for a particular purpose, title and non-infringement. * In no event shall the copyright holder or anyone distributing the * software be liable for any damages or other liability, whether in * contract, tort or otherwise, arising from, out of or in connection * with the software or the use or other dealings in the software. ****************************************************************************/ #include #include #include #include // Function and data structure declarations static bool is_little_endian(); typedef union { double numeric_rep; uint64_t integer_rep; } double_t; typedef union { float numeric_rep; uint32_t integer_rep; } float_t; // A local helper function static bool is_little_endian() { short word{ 0x0001 }; return *reinterpret_cast( &word ); } /**************************************************************************** * Printing in hexadecimal ****************************************************************************/ template std::ostream &operator<<( ece204::hex_ostream_t hos, T const &x ) { return hos.os << x; } std::ostream &operator<<( ece204::hex_ostream_t hos, long double x ) { unsigned char *p_x{ reinterpret_cast( &x ) }; char old_fill{ hos.os.fill( '0' ) }; hos.os << std::hex; if ( is_little_endian() ) { hos.os << std::setw( 2 ) << (+p_x[9] & 0xff) << std::setw( 2 ) << (+p_x[8] & 0xff) << '|'; for ( std::size_t k{8}; k --> 0; ) { hos.os << std::setw( 2 ) << (+p_x[k] & 0xff); } } else { hos.os << std::setw( 2 ) << (+p_x[0] & 0xff) << std::setw( 2 ) << (+p_x[1] & 0xff) << '|'; for ( std::size_t k{2}; k < 10; ++k ) { hos.os << std::setw( 2 ) << (+p_x[k] & 0xff); } } hos.os << std::dec; hos.os.fill( old_fill ); return hos.os; } std::ostream &operator<<( ece204::hex_ostream_t hos, double x ) { double_t y{.numeric_rep = x}; char old_fill{ hos.os.fill( '0' ) }; hos.os << std::hex << std::setw( 3 ) << (y.integer_rep >> 52) << '|' << std::setw( 13 ) << (y.integer_rep & 0xfffffffffffff) << std::dec; hos.os.fill( old_fill ); return hos.os; } std::ostream &operator<<( ece204::hex_ostream_t hos, float x ) { float_t y{.numeric_rep = x}; char old_fill{ hos.os.fill( '0' ) }; hos.os << std::hex << std::setw( 8 ) << y.integer_rep << std::dec; hos.os.fill( old_fill ); return hos.os; } /**************************************************************************** * Printing in octal ****************************************************************************/ template std::ostream &operator<<( ece204::oct_ostream_t oos, T const &x ) { return oos.os << x; } std::ostream &operator<<( ece204::oct_ostream_t oos, double x ) { double_t y{.numeric_rep = x}; char old_fill{ oos.os.fill( '0' ) }; oos.os << std::setw( 4 ) << std::oct << (y.integer_rep >> 52) << '|' << std::setw( 18 ) << ((y.integer_rep & 0xfffffffffffff) << 2) << std::dec; oos.os.fill( old_fill ); return oos.os; } std::ostream &operator<<( ece204::oct_ostream_t oos, float x ) { float_t y{.numeric_rep = x}; char old_fill{ oos.os.fill( '0' ) }; oos.os << std::setw( 3 ) << std::oct << (y.integer_rep >> 23) << '|' << std::setw( 8 ) << ((y.integer_rep & 0x7fffff) << 1) << std::dec; oos.os.fill( old_fill ); return oos.os; } /**************************************************************************** * Printing in binary ****************************************************************************/ template std::ostream &operator<<( ece204::bin_ostream_t bos, T const &x ) { return bos.os << x; } std::ostream &operator<<( ece204::bin_ostream_t bos, long double x ) { unsigned char *p_x{ reinterpret_cast( &x ) }; if ( is_little_endian() ) { bos.os << std::bitset<1>( +p_x[9] >> 7 ) << '|' << std::bitset<7>( +p_x[9] & 0x7f ) << std::bitset<8>( +p_x[8] ) << '|' << std::bitset<1>( +p_x[7] >> 7 ) << '.' << std::bitset<7>( +p_x[7] & 0x7f ); for ( std::size_t k{7}; k --> 0; ) { bos.os << std::bitset<8>( p_x[k] ); } return bos.os; } else { bos.os << std::bitset<1>( +p_x[0] >> 7 ) << '|' << std::bitset<7>( +p_x[0] & 0x7f ) << std::bitset<8>( +p_x[1] ) << std::bitset<1>( +p_x[2] >> 7 ) << '|' << std::bitset<7>( +p_x[2] & 0x7f ); for ( std::size_t k{3}; k < 10; ++k ) { bos.os << std::bitset<8>( p_x[k] ); } return bos.os; } } std::ostream &operator<<( ece204::bin_ostream_t bos, double x ) { double_t y{.numeric_rep = x}; return bos.os << std::bitset<1>( y.integer_rep >> 63 ) << '|' << std::bitset<11>( (y.integer_rep >> 52) & 0x7ff ) << '|' << std::bitset<52>( y.integer_rep & 0xfffffffffffff ); } std::ostream &operator<<( ece204::bin_ostream_t bos, float x ) { float_t y{.numeric_rep = x}; return bos.os << std::bitset<1>( y.integer_rep >> 31 ) << '|' << std::bitset<8>( (y.integer_rep >> 23) & 0xff ) << '|' << std::bitset<23>( y.integer_rep & 0x7fffff ); }