Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 09:40:55

0001 // Copyright 2017 The Abseil Authors.
0002 //
0003 // Licensed under the Apache License, Version 2.0 (the "License");
0004 // you may not use this file except in compliance with the License.
0005 // You may obtain a copy of the License at
0006 //
0007 //      https://www.apache.org/licenses/LICENSE-2.0
0008 //
0009 // Unless required by applicable law or agreed to in writing, software
0010 // distributed under the License is distributed on an "AS IS" BASIS,
0011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0012 // See the License for the specific language governing permissions and
0013 // limitations under the License.
0014 
0015 #ifndef ABSL_RANDOM_INTERNAL_IOSTREAM_STATE_SAVER_H_
0016 #define ABSL_RANDOM_INTERNAL_IOSTREAM_STATE_SAVER_H_
0017 
0018 #include <cmath>
0019 #include <iostream>
0020 #include <limits>
0021 #include <type_traits>
0022 
0023 #include "absl/meta/type_traits.h"
0024 #include "absl/numeric/int128.h"
0025 
0026 namespace absl {
0027 ABSL_NAMESPACE_BEGIN
0028 namespace random_internal {
0029 
0030 // The null_state_saver does nothing.
0031 template <typename T>
0032 class null_state_saver {
0033  public:
0034   using stream_type = T;
0035   using flags_type = std::ios_base::fmtflags;
0036 
0037   null_state_saver(T&, flags_type) {}
0038   ~null_state_saver() {}
0039 };
0040 
0041 // ostream_state_saver is a RAII object to save and restore the common
0042 // basic_ostream flags used when implementing `operator <<()` on any of
0043 // the absl random distributions.
0044 template <typename OStream>
0045 class ostream_state_saver {
0046  public:
0047   using ostream_type = OStream;
0048   using flags_type = std::ios_base::fmtflags;
0049   using fill_type = typename ostream_type::char_type;
0050   using precision_type = std::streamsize;
0051 
0052   ostream_state_saver(ostream_type& os,  // NOLINT(runtime/references)
0053                       flags_type flags, fill_type fill)
0054       : os_(os),
0055         flags_(os.flags(flags)),
0056         fill_(os.fill(fill)),
0057         precision_(os.precision()) {
0058     // Save state in initialized variables.
0059   }
0060 
0061   ~ostream_state_saver() {
0062     // Restore saved state.
0063     os_.precision(precision_);
0064     os_.fill(fill_);
0065     os_.flags(flags_);
0066   }
0067 
0068  private:
0069   ostream_type& os_;
0070   const flags_type flags_;
0071   const fill_type fill_;
0072   const precision_type precision_;
0073 };
0074 
0075 #if defined(__NDK_MAJOR__) && __NDK_MAJOR__ < 16
0076 #define ABSL_RANDOM_INTERNAL_IOSTREAM_HEXFLOAT 1
0077 #else
0078 #define ABSL_RANDOM_INTERNAL_IOSTREAM_HEXFLOAT 0
0079 #endif
0080 
0081 template <typename CharT, typename Traits>
0082 ostream_state_saver<std::basic_ostream<CharT, Traits>> make_ostream_state_saver(
0083     std::basic_ostream<CharT, Traits>& os,  // NOLINT(runtime/references)
0084     std::ios_base::fmtflags flags = std::ios_base::dec | std::ios_base::left |
0085 #if ABSL_RANDOM_INTERNAL_IOSTREAM_HEXFLOAT
0086                                     std::ios_base::fixed |
0087 #endif
0088                                     std::ios_base::scientific) {
0089   using result_type = ostream_state_saver<std::basic_ostream<CharT, Traits>>;
0090   return result_type(os, flags, os.widen(' '));
0091 }
0092 
0093 template <typename T>
0094 typename absl::enable_if_t<!std::is_base_of<std::ios_base, T>::value,
0095                            null_state_saver<T>>
0096 make_ostream_state_saver(T& is,  // NOLINT(runtime/references)
0097                          std::ios_base::fmtflags flags = std::ios_base::dec) {
0098   std::cerr << "null_state_saver";
0099   using result_type = null_state_saver<T>;
0100   return result_type(is, flags);
0101 }
0102 
0103 // stream_precision_helper<type>::kPrecision returns the base 10 precision
0104 // required to stream and reconstruct a real type exact binary value through
0105 // a binary->decimal->binary transition.
0106 template <typename T>
0107 struct stream_precision_helper {
0108   // max_digits10 may be 0 on MSVC; if so, use digits10 + 3.
0109   static constexpr int kPrecision =
0110       (std::numeric_limits<T>::max_digits10 > std::numeric_limits<T>::digits10)
0111           ? std::numeric_limits<T>::max_digits10
0112           : (std::numeric_limits<T>::digits10 + 3);
0113 };
0114 
0115 template <>
0116 struct stream_precision_helper<float> {
0117   static constexpr int kPrecision = 9;
0118 };
0119 template <>
0120 struct stream_precision_helper<double> {
0121   static constexpr int kPrecision = 17;
0122 };
0123 template <>
0124 struct stream_precision_helper<long double> {
0125   static constexpr int kPrecision = 36;  // assuming fp128
0126 };
0127 
0128 // istream_state_saver is a RAII object to save and restore the common
0129 // std::basic_istream<> flags used when implementing `operator >>()` on any of
0130 // the absl random distributions.
0131 template <typename IStream>
0132 class istream_state_saver {
0133  public:
0134   using istream_type = IStream;
0135   using flags_type = std::ios_base::fmtflags;
0136 
0137   istream_state_saver(istream_type& is,  // NOLINT(runtime/references)
0138                       flags_type flags)
0139       : is_(is), flags_(is.flags(flags)) {}
0140 
0141   ~istream_state_saver() { is_.flags(flags_); }
0142 
0143  private:
0144   istream_type& is_;
0145   flags_type flags_;
0146 };
0147 
0148 template <typename CharT, typename Traits>
0149 istream_state_saver<std::basic_istream<CharT, Traits>> make_istream_state_saver(
0150     std::basic_istream<CharT, Traits>& is,  // NOLINT(runtime/references)
0151     std::ios_base::fmtflags flags = std::ios_base::dec |
0152                                     std::ios_base::scientific |
0153                                     std::ios_base::skipws) {
0154   using result_type = istream_state_saver<std::basic_istream<CharT, Traits>>;
0155   return result_type(is, flags);
0156 }
0157 
0158 template <typename T>
0159 typename absl::enable_if_t<!std::is_base_of<std::ios_base, T>::value,
0160                            null_state_saver<T>>
0161 make_istream_state_saver(T& is,  // NOLINT(runtime/references)
0162                          std::ios_base::fmtflags flags = std::ios_base::dec) {
0163   using result_type = null_state_saver<T>;
0164   return result_type(is, flags);
0165 }
0166 
0167 // stream_format_type<T> is a helper struct to convert types which
0168 // basic_iostream cannot output as decimal numbers into types which
0169 // basic_iostream can output as decimal numbers. Specifically:
0170 // * signed/unsigned char-width types are converted to int.
0171 // * TODO(lar): __int128 => uint128, except there is no operator << yet.
0172 //
0173 template <typename T>
0174 struct stream_format_type
0175     : public std::conditional<(sizeof(T) == sizeof(char)), int, T> {};
0176 
0177 // stream_u128_helper allows us to write out either absl::uint128 or
0178 // __uint128_t types in the same way, which enables their use as internal
0179 // state of PRNG engines.
0180 template <typename T>
0181 struct stream_u128_helper;
0182 
0183 template <>
0184 struct stream_u128_helper<absl::uint128> {
0185   template <typename IStream>
0186   inline absl::uint128 read(IStream& in) {
0187     uint64_t h = 0;
0188     uint64_t l = 0;
0189     in >> h >> l;
0190     return absl::MakeUint128(h, l);
0191   }
0192 
0193   template <typename OStream>
0194   inline void write(absl::uint128 val, OStream& out) {
0195     uint64_t h = absl::Uint128High64(val);
0196     uint64_t l = absl::Uint128Low64(val);
0197     out << h << out.fill() << l;
0198   }
0199 };
0200 
0201 #ifdef ABSL_HAVE_INTRINSIC_INT128
0202 template <>
0203 struct stream_u128_helper<__uint128_t> {
0204   template <typename IStream>
0205   inline __uint128_t read(IStream& in) {
0206     uint64_t h = 0;
0207     uint64_t l = 0;
0208     in >> h >> l;
0209     return (static_cast<__uint128_t>(h) << 64) | l;
0210   }
0211 
0212   template <typename OStream>
0213   inline void write(__uint128_t val, OStream& out) {
0214     uint64_t h = static_cast<uint64_t>(val >> 64u);
0215     uint64_t l = static_cast<uint64_t>(val);
0216     out << h << out.fill() << l;
0217   }
0218 };
0219 #endif
0220 
0221 template <typename FloatType, typename IStream>
0222 inline FloatType read_floating_point(IStream& is) {
0223   static_assert(std::is_floating_point<FloatType>::value, "");
0224   FloatType dest;
0225   is >> dest;
0226   // Parsing a double value may report a subnormal value as an error
0227   // despite being able to represent it.
0228   // See https://stackoverflow.com/q/52410931/3286653
0229   // It may also report an underflow when parsing DOUBLE_MIN as an
0230   // ERANGE error, as the parsed value may be smaller than DOUBLE_MIN
0231   // and rounded up.
0232   // See: https://stackoverflow.com/q/42005462
0233   if (is.fail() &&
0234       (std::fabs(dest) == (std::numeric_limits<FloatType>::min)() ||
0235        std::fpclassify(dest) == FP_SUBNORMAL)) {
0236     is.clear(is.rdstate() & (~std::ios_base::failbit));
0237   }
0238   return dest;
0239 }
0240 
0241 }  // namespace random_internal
0242 ABSL_NAMESPACE_END
0243 }  // namespace absl
0244 
0245 #endif  // ABSL_RANDOM_INTERNAL_IOSTREAM_STATE_SAVER_H_