// // This file is part of // // CTBignum // // C++ Library for Compile-Time and Run-Time Multi-Precision and Modular Arithmetic // // // This file is distributed under the Apache License, Version 2.0. See the LICENSE // file for details. #ifndef CT_INPUTOUTPUT_HPP #define CT_INPUTOUTPUT_HPP #include #include #include #include #include #include namespace cbn { template struct Radix10 { using character_t = char; static constexpr T radix = 10; static constexpr size_t representation_length_upper_bound(size_t bit_length_upper_bound) { return (25 * bit_length_upper_bound + 82) / 83; // 25/83 =approx= log(2)/log(10) } static character_t represent(T x) { return 48 + static_cast(x); } static constexpr const char *prefix = ""; }; template struct Radix16 { using character_t = char; static constexpr T radix = 16; static constexpr size_t representation_length_upper_bound(size_t bit_length_upper_bound) { return (bit_length_upper_bound + 3) / 4; } static character_t represent(T x) { if (x <= 9) return 48 + static_cast(x); // ascii: 0..9 else return 87 + static_cast(x); // ascii: a..f } static constexpr const char *prefix = "0x"; }; template auto convert_radix(cbn::big_int obj) { // Return a representation of the big-integer in a user-specified radix // // this should be constant time (not verified yet) using namespace cbn; constexpr size_t bit_length_upper_bound = N * std::numeric_limits::digits; constexpr size_t max_digits = Radix::representation_length_upper_bound(bit_length_upper_bound); std::array radix_repr; for (auto i = 0; i < max_digits; ++i) { auto qr = div(obj, std::integer_sequence{}); detail::assign(obj, qr.quotient); radix_repr[max_digits - 1 - i] = Radix::represent(qr.remainder[0]); } return radix_repr; } template std::ostream &operator<<(std::ostream &strm, cbn::big_int num) { // Write a base-10 representation of the big-integer to the stream using Radix = Radix10; auto buf = convert_radix(num); // remove leading zeros, except the last zero if obj == 0 int offset = 0; auto one_before_end = buf.cend() - 1; for (auto it = buf.cbegin(); it != one_before_end; ++it) { if (*it != Radix::represent(static_cast(0))) break; ++offset; } strm << Radix::prefix; strm.write(buf.cbegin() + offset, buf.size() - offset); return strm; } } #endif