Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions include/fast_io_core_impl/integers/chrono.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ inline constexpr parse_result<char_type const *> chrono_scan_year_impl(char_type
}
if (details::char_is_digit<10, char_type>(*itr)) [[unlikely]]
{
auto [itr2, ec] = scan_int_contiguous_define_impl<10, true, false, false>(begin, end, retval);
auto [itr2, ec] = scan_int_contiguous_define_impl<10, true, false, false, false>(begin, end, retval);
if (ec != parse_code::ok) [[unlikely]]
{
return {itr, ec};
Expand Down Expand Up @@ -198,7 +198,7 @@ chrono_scan_decimal_fraction_part_never_overflow_impl(char_type const *begin, ch
{
new_end = end;
}
auto [itr, ec] = scan_int_contiguous_define_impl<10, true, false, true>(begin, new_end, retval);
auto [itr, ec] = scan_int_contiguous_define_impl<10, true, false, true, false>(begin, new_end, retval);
if (ec != parse_code::ok) [[unlikely]]
{
return {itr, ec};
Expand Down
221 changes: 127 additions & 94 deletions include/fast_io_core_impl/integers/impl.h

Large diffs are not rendered by default.

13 changes: 9 additions & 4 deletions include/fast_io_core_impl/integers/ordinal.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,12 @@ inline constexpr auto ordinal(T t) noexcept
namespace details
{

template <::std::size_t base, bool showbase, bool uppercase_showbase, bool showpos, bool uppercase, bool full, ::std::integral char_type, typename T>
template <::std::size_t base, bool showbase, bool uppercase_showbase, bool showpos, bool uppercase, bool full,
bool modern_octal, ::std::integral char_type, typename T>
inline constexpr char_type *prrsv_ordinal_impl(char_type *iter, T t) noexcept
{
iter = ::fast_io::details::print_reserve_integral_define<base, showbase, uppercase_showbase, showpos, uppercase, full>(iter, t);
iter = ::fast_io::details::print_reserve_integral_define<base, showbase, uppercase_showbase, showpos, uppercase,
full, modern_octal>(iter, t);
std::uint_least8_t prefix_kind{};
if (t / 100 % 10 == 1)
{
Expand Down Expand Up @@ -78,13 +80,16 @@ inline constexpr char_type *prrsv_ordinal_impl(char_type *iter, T t) noexcept
template <::std::integral char_type, ::fast_io::manipulators::scalar_flags flags, ::fast_io::details::my_integral T>
inline constexpr ::std::size_t print_reserve_size(::fast_io::io_reserve_type_t<char_type, ::fast_io::manipulators::scalar_manip_t<flags, ::fast_io::manipulators::ordinal_t<T>>>)
{
return ::fast_io::details::print_integer_reserved_size_cache<flags.base, flags.showbase, flags.showpos, T> + 2u;
return ::fast_io::details::print_integer_reserved_size_cache<flags.base, flags.showbase, flags.showpos, flags.modern_octal, T> +
2u;
}

template <::std::integral char_type, ::fast_io::manipulators::scalar_flags flags, typename T>
inline constexpr char_type *print_reserve_define(::fast_io::io_reserve_type_t<char_type, ::fast_io::manipulators::scalar_manip_t<flags, ::fast_io::manipulators::ordinal_t<T>>>, char_type *iter, ::fast_io::manipulators::scalar_manip_t<flags, ::fast_io::manipulators::ordinal_t<T>> t) noexcept
{
return ::fast_io::details::prrsv_ordinal_impl<flags.base, flags.showbase, flags.uppercase_showbase, flags.showpos, flags.uppercase, flags.full>(iter, t.reference.reference);
return ::fast_io::details::prrsv_ordinal_impl<flags.base, flags.showbase, flags.uppercase_showbase, flags.showpos,
flags.uppercase, flags.full, flags.modern_octal>(iter,
t.reference.reference);
}

} // namespace fast_io
96 changes: 52 additions & 44 deletions include/fast_io_core_impl/integers/percentage.h

Large diffs are not rendered by default.

83 changes: 43 additions & 40 deletions include/fast_io_core_impl/integers/sto/sto_contiguous.h
Original file line number Diff line number Diff line change
Expand Up @@ -257,8 +257,8 @@ struct simd_parse_result
inline constexpr char unsigned simd16_shift_table[32]{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 1, 2, 3, 4, 5,
6, 7, 8, 9, 10, 11, 12, 13, 14, 15};

#if defined(__SSE4_1__) && (defined(__x86_64__) || defined(_M_AMD64))
// aarch64ec also defines x86_64 macro
#if defined(__SSE4_1__) && ((defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64)) && !(defined(__arm64ec__) || defined(_M_ARM64EC)))

template <bool char_execharset>
inline ::std::uint_least32_t detect_length(char unsigned const *buffer) noexcept
Expand Down Expand Up @@ -945,7 +945,7 @@ scan_int_contiguous_none_simd_space_part_define_impl(char_type const *first, cha

inline constexpr parse_code ongoing_parse_code{static_cast<parse_code>(::std::numeric_limits<char unsigned>::max())};

template <char8_t base, ::std::integral char_type>
template <char8_t base, bool modern_octal, ::std::integral char_type>
inline constexpr parse_result<char_type const *> scan_shbase_impl(char_type const *first,
char_type const *last) noexcept
{
Expand All @@ -957,11 +957,11 @@ inline constexpr parse_result<char_type const *> scan_shbase_impl(char_type cons
{
return {first, parse_code::invalid};
}
if constexpr (base == 2 || base == 3 || base == 16)
if constexpr (base == 2 || base == 3 || (base == 8 && modern_octal) || base == 16)
{
auto ch{*first};
if ((ch != char_literal_v<(base == 2 ? u8'B' : (base == 3 ? u8't' : u8'X')), char_type>)&(
ch != char_literal_v<(base == 2 ? u8'b' : (base == 3 ? u8't' : u8'x')), char_type>)) [[unlikely]]
if ((ch != char_literal_v<(base == 2 ? u8'B' : (base == 3 ? u8't' : (base == 8 ? u8'O' : u8'X'))), char_type>)&(
ch != char_literal_v<(base == 2 ? u8'b' : (base == 3 ? u8't' : (base == 8 ? u8'o' : u8'x'))), char_type>)) [[unlikely]]
{
return {first, parse_code::invalid};
}
Expand Down Expand Up @@ -1010,7 +1010,7 @@ inline constexpr parse_result<char_type const *> scan_shbase_impl(char_type cons
template <::std::integral char_type>
inline constexpr char_type const *skip_hexdigits(char_type const *first, char_type const *last) noexcept;

template <char8_t base, bool shbase = false, bool skipzero = false, ::std::integral char_type, my_integral T>
template <char8_t base, bool shbase = false, bool skipzero = false, bool modern_octal = false, ::std::integral char_type, my_integral T>
inline constexpr parse_result<char_type const *>
scan_int_contiguous_none_space_part_define_impl(char_type const *first, char_type const *last, T &t) noexcept
{
Expand All @@ -1029,7 +1029,7 @@ scan_int_contiguous_none_space_part_define_impl(char_type const *first, char_typ
}
if constexpr (shbase && base != 10)
{
if constexpr (base == 8)
if constexpr (base == 8 && !modern_octal)
{
if (first == last || *first != char_literal_v<u8'0', char_type>) [[unlikely]]
{
Expand All @@ -1039,7 +1039,7 @@ scan_int_contiguous_none_space_part_define_impl(char_type const *first, char_typ
}
else
{
auto phase_ret = scan_shbase_impl<base>(first, last);
auto phase_ret = scan_shbase_impl<base, modern_octal>(first, last);
if (phase_ret.code != ongoing_parse_code) [[unlikely]]
{
return phase_ret;
Expand Down Expand Up @@ -1083,7 +1083,7 @@ scan_int_contiguous_none_space_part_define_impl(char_type const *first, char_typ
using unsigned_type = my_make_unsigned_t<::std::remove_cvref_t<T>>;
unsigned_type res{};
char_type const *it;
#if defined(__SSE4_1__) && (defined(__x86_64__) || defined(_M_AMD64))
#if defined(__SSE4_1__) && ((defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64)) && !(defined(__arm64ec__) || defined(_M_ARM64EC)))
if constexpr (base == 10 && sizeof(char_type) == 1 && sizeof(unsigned_type) <= sizeof(::std::uint_least64_t))
{
if (
Expand Down Expand Up @@ -1159,7 +1159,8 @@ scan_int_contiguous_none_space_part_define_impl(char_type const *first, char_typ
return {it, parse_code::ok};
}

template <char8_t base, bool noskipws, bool shbase, bool skipzero, ::std::integral char_type, details::my_integral T>
template <char8_t base, bool noskipws, bool shbase, bool skipzero, bool modern_octal, ::std::integral char_type,
details::my_integral T>
inline constexpr parse_result<char_type const *> scan_int_contiguous_define_impl(char_type const *first,
char_type const *last, T &t) noexcept
{
Expand All @@ -1175,7 +1176,7 @@ inline constexpr parse_result<char_type const *> scan_int_contiguous_define_impl
{
if constexpr (shbase && base != 10)
{
if constexpr (base == 8)
if constexpr (base == 8 && !modern_octal)
{
if (first == last || *first != char_literal_v<u8'0', char_type>) [[unlikely]]
{
Expand All @@ -1185,7 +1186,7 @@ inline constexpr parse_result<char_type const *> scan_int_contiguous_define_impl
}
else
{
auto phase_ret = scan_shbase_impl<base>(first, last);
auto phase_ret = scan_shbase_impl<base, modern_octal>(first, last);
if (phase_ret.code != ongoing_parse_code) [[unlikely]]
{
return phase_ret;
Expand All @@ -1195,7 +1196,7 @@ inline constexpr parse_result<char_type const *> scan_int_contiguous_define_impl
}
}
return scan_int_contiguous_none_space_part_define_impl<base, ((shbase && base != 10) && my_signed_integral<T>),
skipzero>(first, last, t);
skipzero, modern_octal>(first, last, t);
}
} // namespace details

Expand All @@ -1219,7 +1220,7 @@ inline constexpr auto scan_context_type_impl_int() noexcept
using unsigned_type = details::my_make_unsigned_t<::std::remove_cvref_t<T>>;
constexpr ::std::size_t max_size{
(::fast_io::details::print_integer_reserved_size_cache<base, false, ::fast_io::details::my_signed_integral<T>,
unsigned_type>)+2};
false, unsigned_type>) + 2};
struct scan_integer_context
{
::fast_io::freestanding::array<char_type, max_size> buffer;
Expand Down Expand Up @@ -1299,7 +1300,7 @@ inline constexpr parse_result<char_type const *> sc_int_ctx_sign_phase(State &st
return {first, ongoing_parse_code};
}

template <char8_t base, ::std::integral char_type>
template <char8_t base, bool modern_octal, ::std::integral char_type>
requires(base != 10)
inline constexpr parse_result<char_type const *>
sc_int_ctx_prefix_phase(::std::uint_least8_t &sz, char_type const *first, char_type const *last) noexcept
Expand All @@ -1308,7 +1309,7 @@ sc_int_ctx_prefix_phase(::std::uint_least8_t &sz, char_type const *first, char_t
{
return {first, parse_code::partial};
}
if constexpr (base == 8)
if constexpr (base == 8 && !modern_octal)
{
if (*first != char_literal_v<u8'0', char_type>) [[unlikely]]
{
Expand All @@ -1334,11 +1335,11 @@ sc_int_ctx_prefix_phase(::std::uint_least8_t &sz, char_type const *first, char_t
size_cache = 1;
}
}
if constexpr (base == 2 || base == 3 || base == 16)
if constexpr (base == 2 || base == 3 || (base == 8 && modern_octal) || base == 16)
{
auto ch{*first};
if ((ch == char_literal_v<(base == 2 ? u8'B' : (base == 3 ? u8't' : u8'X')), char_type>) |
(ch == char_literal_v<(base == 2 ? u8'b' : (base == 3 ? u8't' : u8'x')), char_type>)) [[likely]]
if ((ch == char_literal_v<(base == 2 ? u8'B' : (base == 3 ? u8't' : (base == 8 ? u8'O' : u8'X'))), char_type>) |
(ch == char_literal_v<(base == 2 ? u8'b' : (base == 3 ? u8't' : (base == 8 ? u8'o' : u8'x'))), char_type>)) [[likely]]
{
sz = 0;
++first;
Expand Down Expand Up @@ -1455,7 +1456,7 @@ inline constexpr parse_result<char_type const *> sc_int_ctx_zero_phase(scan_inte
return {first, ongoing_parse_code};
}

template <char8_t base, ::std::integral char_type, typename State, my_integral T>
template <char8_t base, bool modern_octal, ::std::integral char_type, typename State, my_integral T>
inline constexpr parse_result<char_type const *> sc_int_ctx_digit_phase(State &st, char_type const *first,
char_type const *last, T &t) noexcept
{
Expand All @@ -1477,7 +1478,7 @@ inline constexpr parse_result<char_type const *> sc_int_ctx_digit_phase(State &s
t = {};
return {it, parse_code::ok};
}
auto [p, ec] = scan_int_contiguous_none_space_part_define_impl<base>(st.buffer.data(), e, t);
auto [p, ec] = scan_int_contiguous_none_space_part_define_impl<base, false, false, modern_octal>(st.buffer.data(), e, t);
return {p - start + first, ec};
}
else
Expand Down Expand Up @@ -1519,8 +1520,8 @@ inline constexpr parse_result<char_type const *> sc_int_ctx_skip_digits_phase(ch
return {first, (first == last) ? parse_code::partial : parse_code::invalid};
}

template <char8_t base, bool noskipws, bool shbase, bool skipzero, typename State, ::std::integral char_type,
my_integral T>
template <char8_t base, bool noskipws, bool shbase, bool skipzero, bool modern_octal, typename State,
::std::integral char_type, my_integral T>
inline constexpr parse_result<char_type const *> scan_context_define_parse_impl(State &st, char_type const *first,
char_type const *last, T &t) noexcept
{
Expand Down Expand Up @@ -1580,7 +1581,7 @@ inline constexpr parse_result<char_type const *> scan_context_define_parse_impl(
if constexpr (shbase && base != 10)
{
st.integer_phase = scan_integral_context_phase::prefix;
auto phase_ret = sc_int_ctx_prefix_phase<base>(st.size, first, last);
auto phase_ret = sc_int_ctx_prefix_phase<base, modern_octal>(st.size, first, last);
if (phase_ret.code != ongoing_parse_code) [[unlikely]]
{
return phase_ret;
Expand Down Expand Up @@ -1621,7 +1622,7 @@ inline constexpr parse_result<char_type const *> scan_context_define_parse_impl(
}
case scan_integral_context_phase::digit:
{
return sc_int_ctx_digit_phase<base>(st, first, last, t);
return sc_int_ctx_digit_phase<base, modern_octal>(st, first, last, t);
}
case scan_integral_context_phase::zero_invalid:
{
Expand All @@ -1646,7 +1647,7 @@ inline constexpr parse_result<char_type const *> scan_context_define_parse_impl(
}
}

template <char8_t base, bool noskipws, bool shbase, bool skipzero, typename State, my_integral T>
template <char8_t base, bool noskipws, bool shbase, bool skipzero, bool modern_octal, typename State, my_integral T>
#if __has_cpp_attribute(__gnu__::__cold__)
[[__gnu__::__cold__]]
#endif
Expand All @@ -1673,7 +1674,7 @@ inline constexpr parse_code scan_context_eof_define_parse_impl(State &st, T &t)
}
}
case scan_integral_context_phase::digit:
return scan_int_contiguous_none_space_part_define_impl<base>(st.buffer.data(), st.buffer.data() + st.size, t).code;
return scan_int_contiguous_none_space_part_define_impl<base, false, false, modern_octal>(st.buffer.data(), st.buffer.data() + st.size, t).code;
case scan_integral_context_phase::overflow:
return parse_code::overflow;
case scan_integral_context_phase::zero_skip:
Expand Down Expand Up @@ -1705,49 +1706,51 @@ inline constexpr ch_get_t<T &> ch_get(T &reference) noexcept
return {reference};
}

template <::std::size_t bs, bool noskipws = false, bool skipzero = false, bool prefix = false, ::fast_io::details::my_integral scalar_type>
template <::std::size_t bs, bool noskipws = false, bool skipzero = false, bool prefix = false, bool modern_octal = false,
::fast_io::details::my_integral scalar_type>
requires(2 <= bs && bs <= 36)
inline constexpr scalar_manip_t<::fast_io::details::base_scan_mani_flags_cache<bs, noskipws, (bs == 10 ? false : prefix), skipzero>,
inline constexpr scalar_manip_t<::fast_io::details::base_scan_mani_flags_cache<bs, noskipws, (bs == 10 ? false : prefix), skipzero, modern_octal>,
scalar_type &>
base_get(scalar_type &t) noexcept
{
return {t};
}

template <bool noskipws = false, bool skipzero = false, bool prefix = false, ::fast_io::details::my_integral scalar_type>
inline constexpr scalar_manip_t<::fast_io::details::base_scan_mani_flags_cache<2, noskipws, prefix, skipzero>,
inline constexpr scalar_manip_t<::fast_io::details::base_scan_mani_flags_cache<2, noskipws, prefix, skipzero, false>,
scalar_type &>
bin_get(scalar_type &t) noexcept
{
return {t};
}

template <bool noskipws = false, bool skipzero = false, bool prefix = false, ::fast_io::details::my_integral scalar_type>
inline constexpr scalar_manip_t<::fast_io::details::base_scan_mani_flags_cache<8, noskipws, prefix, skipzero>,
template <bool noskipws = false, bool skipzero = false, bool prefix = false, bool modern_octal = false, ::fast_io::details::my_integral scalar_type>
inline constexpr scalar_manip_t<::fast_io::details::base_scan_mani_flags_cache<8, noskipws, prefix, skipzero, modern_octal>,
scalar_type &>
oct_get(scalar_type &t) noexcept
{
return {t};
}

template <bool noskipws = false, bool skipzero = false, ::fast_io::details::my_integral scalar_type>
inline constexpr scalar_manip_t<::fast_io::details::base_scan_mani_flags_cache<10, noskipws, false, skipzero>,
inline constexpr scalar_manip_t<::fast_io::details::base_scan_mani_flags_cache<10, noskipws, false, skipzero, false>,
scalar_type &>
dec_get(scalar_type &t) noexcept
{
return {t};
}

template <bool noskipws = false, bool skipzero = false, bool prefix = false, ::fast_io::details::my_integral scalar_type>
inline constexpr scalar_manip_t<::fast_io::details::base_scan_mani_flags_cache<16, noskipws, prefix, skipzero>,
inline constexpr scalar_manip_t<::fast_io::details::base_scan_mani_flags_cache<16, noskipws, prefix, skipzero, false>,
scalar_type &>
hex_get(scalar_type &t) noexcept
{
return {t};
}

template <bool noskipws = false, ::fast_io::details::my_unsigned_integral scalar_type>
inline constexpr scalar_manip_t<::fast_io::details::base_scan_mani_flags_cache<16, noskipws, true, true>, scalar_type &>
inline constexpr scalar_manip_t<::fast_io::details::base_scan_mani_flags_cache<16, noskipws, true, true, false>,
scalar_type &>
addrvw_get(scalar_type &t) noexcept
{
return {t};
Expand All @@ -1757,7 +1760,7 @@ addrvw_get(scalar_type &t) noexcept

template <details::my_integral T>
inline constexpr ::fast_io::manipulators::scalar_manip_t<
::fast_io::details::base_scan_mani_flags_cache<10, false, false, false>, T &>
::fast_io::details::base_scan_mani_flags_cache<10, false, false, false, false>, T &>
scan_alias_define(io_alias_t, T &t) noexcept
{
return {t};
Expand All @@ -1776,7 +1779,7 @@ scan_contiguous_define(io_reserve_type_t<char_type, ::fast_io::manipulators::sca
char_type const *begin, char_type const *end,
::fast_io::manipulators::scalar_manip_t<flags, T &> t) noexcept
{
return details::scan_int_contiguous_define_impl<flags.base, flags.noskipws, flags.showbase, flags.full>(
return details::scan_int_contiguous_define_impl<flags.base, flags.noskipws, flags.showbase, flags.full, flags.modern_octal>(
begin, end, t.reference);
}

Expand All @@ -1786,7 +1789,7 @@ scan_context_define(io_reserve_type_t<char_type, ::fast_io::manipulators::scalar
char_type const *begin, char_type const *end,
::fast_io::manipulators::scalar_manip_t<flags, T &> t) noexcept
{
return details::scan_context_define_parse_impl<flags.base, flags.noskipws, flags.showbase, flags.full>(
return details::scan_context_define_parse_impl<flags.base, flags.noskipws, flags.showbase, flags.full, flags.modern_octal>(
state, begin, end, t.reference);
}

Expand All @@ -1795,7 +1798,7 @@ inline constexpr parse_code
scan_context_eof_define(io_reserve_type_t<char_type, ::fast_io::manipulators::scalar_manip_t<flags, T &>>, State &state,
::fast_io::manipulators::scalar_manip_t<flags, T &> t) noexcept
{
return details::scan_context_eof_define_parse_impl<flags.base, flags.noskipws, flags.showbase, flags.full>(
return details::scan_context_eof_define_parse_impl<flags.base, flags.noskipws, flags.showbase, flags.full, flags.modern_octal>(
state, t.reference);
}

Expand Down
Loading
Loading