#include /**************************************************************************** * Output manipulators for floating-point numbers * * This library introduces two ostream manipulators to print * floating-point numbers in both hexadecimal and binary. * * Use: * double x{ 42.3134765625 }; * std::cout << x << std::endl // prints 42.3135 * << hex << x << std::endl // prints 404|5282000000000 * << oct << x << std::endl // prints 2004|245010000000000000 * << bin << x << std::endl; * // prints 0|10000000100|010100101000001000000..0 * * float y{ -42.3134765625 }; * std::cout << y << std::endl // prints -42.3135 * << hex << y << std::endl // prints c2294100 * << oct << y << std::endl // prints 604|24501000 * << bin << y << std::endl; * // prints 1|10000100|01010010100000100000000 * * long double z{ 3.1415926535897932385L }; * std::cout << z << std::endl // prints 3.14159 * << hex << z << std::endl // prints 4000|c90fdaa22168c235 * << bin << z << std::endl; * // prints 0|100000000000000|1.100100100001111110... * ...110101010001000100001011010001100001000110101 * * The pipes (i.e., '|') are used where possible to separate the sign bit * from the exponent or the exponent from the mantissa, where possible. * The sign bit can only be singled out in the binary representation, but * the exponent and mantissa cannot be separated for the hexadecimal * 'float' representation. * * As none of the floating-point types have a multiple of three number of * bits, the output using octal will have either one or two trailing zeros. * * The std::bitset class is used for printing binary, as while there * is an overhead, the cost is negligable in compared to printing. * * Important: the 'long double' representation stores the leading '1', * so this is clearly shown in the binary printing * * How this all works: * Given his statement where 'ece204::hex' is an instance of * the 'Hex' class: * std::cout << ece204::hex << 3.15 << std::endl; * \______________________/ this returns an instance of 'hex_ostream_t', * | which internally stores a reference to * v 'std::cout' -- nothing is printed * hex_ostream_t << 3.15 << std::endl; * \____________________/ this calls the << routine to print 3.15 * | in the desired format, after which the * v reference to 'std::cout' is returned * std::cout << std::endl; * * References: * Piotr Nycz (how to write an ostream manipulator) * https://stackoverflow.com/questions/40834544/ * Katy (to use bitset) * https://katyscode.wordpress.com/2012/05/12/ * * 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. ****************************************************************************/ namespace ece204 { class Hex { // Emtpy class }; class Oct { // Emtpy class }; class Bin { // Emtpy class }; constexpr Hex hex; constexpr Oct oct; constexpr Bin bin; struct hex_ostream_t { std::ostream &os; }; struct oct_ostream_t { std::ostream &os; }; struct bin_ostream_t { std::ostream &os; }; } inline ece204::hex_ostream_t operator<<( std::ostream &os, ece204::Hex ) { return { os }; } inline ece204::oct_ostream_t operator<<( std::ostream &os, ece204::Oct ) { return { os }; } inline ece204::bin_ostream_t operator<<( std::ostream &os, ece204::Bin ) { return { os }; } template std::ostream &operator<<( ece204::hex_ostream_t hos, T const &x ); std::ostream &operator<<( ece204::hex_ostream_t hos, long double x ); std::ostream &operator<<( ece204::hex_ostream_t hos, double x ); std::ostream &operator<<( ece204::hex_ostream_t hos, float x ); template std::ostream &operator<<( ece204::oct_ostream_t oos, T const &x ); // Printing of long double in octal is not implemented // std::ostream &operator<<( ece204::oct_ostream_t oos, long double x ); std::ostream &operator<<( ece204::oct_ostream_t oos, double x ); std::ostream &operator<<( ece204::oct_ostream_t oos, float x ); template std::ostream &operator<<( ece204::bin_ostream_t bos, T const &x ); std::ostream &operator<<( ece204::bin_ostream_t bos, long double x ); std::ostream &operator<<( ece204::bin_ostream_t bos, double x ); std::ostream &operator<<( ece204::bin_ostream_t bos, float x ); #include "float_rep.tpp"