Int128
(utilities/int128.hpp)
Overview
Helpers for using GCC/Clang __int128_t and __uint128_t in competitive programming. The header provides aliases, string conversion, parsing, and stream operators.
Aliases
Alias
Type
m1une::utilities::i128
__int128_t
m1une::utilities::u128
__uint128_t
Functions
Function
Description
Complexity / Throws
std::string to_string(i128 x)
Converts a signed 128-bit integer to decimal.
$O(\log x)$
std::string to_string(u128 x)
Converts an unsigned 128-bit integer to decimal.
$O(\log x)$
i128 parse_int128(const std::string& s)
Parses a signed decimal string.
$O(
s
)$; throws std::invalid_argument for invalid input.
u128 parse_uint128(const std::string& s)
Parses an unsigned decimal string.
$O(
s
)$; throws std::invalid_argument for invalid input.
operator<< / operator>>
Reads and writes decimal values through standard streams.
Linear in the number of digits.
Example
#include "utilities/int128.hpp"
#include <iostream>
int main () {
using m1une :: utilities :: i128 ;
i128 x ;
std :: cin >> x ;
x *= 1000000000000000000LL ;
std :: cout << x << " \n " ;
}
Verified with
Code
#ifndef M1UNE_INT128_HPP
#define M1UNE_INT128_HPP 1
#include <algorithm>
#include <cctype>
#include <istream>
#include <ostream>
#include <stdexcept>
#include <string>
namespace m1une {
namespace utilities {
using i128 = __int128_t ;
using u128 = __uint128_t ;
inline std :: string to_string ( u128 x ) {
if ( x == 0 ) {
return "0" ;
}
std :: string s ;
while ( x > 0 ) {
s . push_back ( static_cast < char > ( '0' + x % 10 ));
x /= 10 ;
}
std :: reverse ( s . begin (), s . end ());
return s ;
}
inline std :: string to_string ( i128 x ) {
if ( x < 0 ) {
u128 magnitude = static_cast < u128 > ( - ( x + 1 )) + 1 ;
return "-" + to_string ( magnitude );
}
return to_string ( static_cast < u128 > ( x ));
}
inline u128 parse_uint128 ( const std :: string & s ) {
if ( s . empty ()) {
throw std :: invalid_argument ( "empty string" );
}
u128 value = 0 ;
for ( char c : s ) {
if ( ! std :: isdigit ( static_cast < unsigned char > ( c ))) {
throw std :: invalid_argument ( "invalid unsigned __int128 literal" );
}
value = value * 10 + static_cast < unsigned > ( c - '0' );
}
return value ;
}
inline i128 parse_int128 ( const std :: string & s ) {
if ( s . empty ()) {
throw std :: invalid_argument ( "empty string" );
}
bool negative = s [ 0 ] == '-' ;
std :: size_t pos = ( s [ 0 ] == '-' || s [ 0 ] == '+' ) ? 1 : 0 ;
if ( pos == s . size ()) {
throw std :: invalid_argument ( "invalid __int128 literal" );
}
i128 value = 0 ;
for (; pos < s . size (); ++ pos ) {
char c = s [ pos ];
if ( ! std :: isdigit ( static_cast < unsigned char > ( c ))) {
throw std :: invalid_argument ( "invalid __int128 literal" );
}
int digit = c - '0' ;
value = value * 10 + ( negative ? - digit : digit );
}
return value ;
}
} // namespace utilities
} // namespace m1une
inline std :: ostream & operator << ( std :: ostream & os , __uint128_t x ) {
return os << m1une :: utilities :: to_string ( x );
}
inline std :: ostream & operator << ( std :: ostream & os , __int128_t x ) {
return os << m1une :: utilities :: to_string ( x );
}
inline std :: istream & operator >> ( std :: istream & is , __uint128_t & x ) {
std :: string s ;
is >> s ;
if ( is ) {
x = m1une :: utilities :: parse_uint128 ( s );
}
return is ;
}
inline std :: istream & operator >> ( std :: istream & is , __int128_t & x ) {
std :: string s ;
is >> s ;
if ( is ) {
x = m1une :: utilities :: parse_int128 ( s );
}
return is ;
}
#endif // M1UNE_INT128_HPP
#line 1 "utilities/int128.hpp"
#include <algorithm>
#include <cctype>
#include <istream>
#include <ostream>
#include <stdexcept>
#include <string>
namespace m1une {
namespace utilities {
using i128 = __int128_t ;
using u128 = __uint128_t ;
inline std :: string to_string ( u128 x ) {
if ( x == 0 ) {
return "0" ;
}
std :: string s ;
while ( x > 0 ) {
s . push_back ( static_cast < char > ( '0' + x % 10 ));
x /= 10 ;
}
std :: reverse ( s . begin (), s . end ());
return s ;
}
inline std :: string to_string ( i128 x ) {
if ( x < 0 ) {
u128 magnitude = static_cast < u128 > ( - ( x + 1 )) + 1 ;
return "-" + to_string ( magnitude );
}
return to_string ( static_cast < u128 > ( x ));
}
inline u128 parse_uint128 ( const std :: string & s ) {
if ( s . empty ()) {
throw std :: invalid_argument ( "empty string" );
}
u128 value = 0 ;
for ( char c : s ) {
if ( ! std :: isdigit ( static_cast < unsigned char > ( c ))) {
throw std :: invalid_argument ( "invalid unsigned __int128 literal" );
}
value = value * 10 + static_cast < unsigned > ( c - '0' );
}
return value ;
}
inline i128 parse_int128 ( const std :: string & s ) {
if ( s . empty ()) {
throw std :: invalid_argument ( "empty string" );
}
bool negative = s [ 0 ] == '-' ;
std :: size_t pos = ( s [ 0 ] == '-' || s [ 0 ] == '+' ) ? 1 : 0 ;
if ( pos == s . size ()) {
throw std :: invalid_argument ( "invalid __int128 literal" );
}
i128 value = 0 ;
for (; pos < s . size (); ++ pos ) {
char c = s [ pos ];
if ( ! std :: isdigit ( static_cast < unsigned char > ( c ))) {
throw std :: invalid_argument ( "invalid __int128 literal" );
}
int digit = c - '0' ;
value = value * 10 + ( negative ? - digit : digit );
}
return value ;
}
} // namespace utilities
} // namespace m1une
inline std :: ostream & operator << ( std :: ostream & os , __uint128_t x ) {
return os << m1une :: utilities :: to_string ( x );
}
inline std :: ostream & operator << ( std :: ostream & os , __int128_t x ) {
return os << m1une :: utilities :: to_string ( x );
}
inline std :: istream & operator >> ( std :: istream & is , __uint128_t & x ) {
std :: string s ;
is >> s ;
if ( is ) {
x = m1une :: utilities :: parse_uint128 ( s );
}
return is ;
}
inline std :: istream & operator >> ( std :: istream & is , __int128_t & x ) {
std :: string s ;
is >> s ;
if ( is ) {
x = m1une :: utilities :: parse_int128 ( s );
}
return is ;
}
Back to top page