Skip to content

io.hpp

SECTIONUtility INCLUDEnoya/io.hpp

Fast standard-stream setup and exact signed 128-bit decimal I/O. Disabling C/C++ stream synchronization removes redundant buffering. Decimal parsing accumulates an unsigned magnitude so the minimum signed value is representable; formatting performs the inverse repeated division without ever negating that minimum value in signed arithmetic.

Verified by aplusb, many_aplusb, many_aplusb_128bit.

启用快速标准输入输出,并精确读写有符号 128 位整数。

Implementation

View on GitHub

#ifndef NOYA_IO_HPP
#define NOYA_IO_HPP 1

/// @complexity Time: O(1) setup and O(d) for a d-digit conversion.
/// Space: O(d) for the returned decimal string.

#include <algorithm>
#include <cassert>
#include <iostream>
#include <string>
#include <string_view>

namespace noya {

/// @brief Fast standard-stream setup and exact signed 128-bit decimal I/O.
/// Disabling C/C++ stream synchronization removes redundant buffering. Decimal
/// parsing accumulates an unsigned magnitude so the minimum signed value is
/// representable; formatting performs the inverse repeated division without
/// ever negating that minimum value in signed arithmetic.
inline void fast_io() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(nullptr);
}

inline __int128 parse_int128(std::string_view token) {
  assert(!token.empty());
  bool negative = token.front() == '-';
  bool positive = token.front() == '+';
  std::size_t position = negative || positive;
  assert(position < token.size());
  unsigned __int128 magnitude = 0;
  for (; position < token.size(); ++position) {
    char digit = token[position];
    assert('0' <= digit && digit <= '9');
    magnitude = magnitude * 10 + unsigned(digit - '0');
  }
  constexpr unsigned __int128 sign_bit =
      static_cast<unsigned __int128>(1) << 127;
  assert(magnitude <= (negative ? sign_bit : sign_bit - 1));
  if (!negative) {
    return static_cast<__int128>(magnitude);
  }
  if (magnitude == sign_bit) {
    return -static_cast<__int128>(sign_bit - 1) - 1;
  }
  return -static_cast<__int128>(magnitude);
}

inline std::string to_string_int128(__int128 value) {
  bool negative = value < 0;
  unsigned __int128 magnitude = negative
                                    ? static_cast<unsigned __int128>(-(value + 1)) + 1
                                    : static_cast<unsigned __int128>(value);
  std::string result;
  do {
    result.push_back(char('0' + magnitude % 10));
    magnitude /= 10;
  } while (magnitude != 0);
  if (negative) {
    result.push_back('-');
  }
  std::reverse(result.begin(), result.end());
  return result;
}

} // namespace noya

#endif // NOYA_IO_HPP
#include <algorithm>
#include <cassert>
#include <iostream>
#include <string>
#include <string_view>

/// @complexity Time: O(1) setup and O(d) for a d-digit conversion.
/// Space: O(d) for the returned decimal string.

namespace noya {

/// @brief Fast standard-stream setup and exact signed 128-bit decimal I/O.
/// Disabling C/C++ stream synchronization removes redundant buffering. Decimal
/// parsing accumulates an unsigned magnitude so the minimum signed value is
/// representable; formatting performs the inverse repeated division without
/// ever negating that minimum value in signed arithmetic.
inline void fast_io() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(nullptr);
}

inline __int128 parse_int128(std::string_view token) {
  assert(!token.empty());
  bool negative = token.front() == '-';
  bool positive = token.front() == '+';
  std::size_t position = negative || positive;
  assert(position < token.size());
  unsigned __int128 magnitude = 0;
  for (; position < token.size(); ++position) {
    char digit = token[position];
    assert('0' <= digit && digit <= '9');
    magnitude = magnitude * 10 + unsigned(digit - '0');
  }
  constexpr unsigned __int128 sign_bit =
      static_cast<unsigned __int128>(1) << 127;
  assert(magnitude <= (negative ? sign_bit : sign_bit - 1));
  if (!negative) {
    return static_cast<__int128>(magnitude);
  }
  if (magnitude == sign_bit) {
    return -static_cast<__int128>(sign_bit - 1) - 1;
  }
  return -static_cast<__int128>(magnitude);
}

inline std::string to_string_int128(__int128 value) {
  bool negative = value < 0;
  unsigned __int128 magnitude = negative
                                    ? static_cast<unsigned __int128>(-(value + 1)) + 1
                                    : static_cast<unsigned __int128>(value);
  std::string result;
  do {
    result.push_back(char('0' + magnitude % 10));
    magnitude /= 10;
  } while (magnitude != 0);
  if (negative) {
    result.push_back('-');
  }
  std::reverse(result.begin(), result.end());
  return result;
}

} // namespace noya