Thanks for using Compiler Explorer
Sponsors
Jakt
C++
Ada
Analysis
Android Java
Android Kotlin
Assembly
C
C3
Carbon
C++ (Circle)
CIRCT
Clean
CMake
CMakeScript
COBOL
C++ for OpenCL
MLIR
Cppx
Cppx-Blue
Cppx-Gold
Cpp2-cppfront
Crystal
C#
CUDA C++
D
Dart
Elixir
Erlang
Fortran
F#
Go
Haskell
HLSL
Hook
Hylo
ispc
Java
Julia
Kotlin
LLVM IR
LLVM MIR
Modula-2
Nim
Objective-C
Objective-C++
OCaml
OpenCL C
Pascal
Pony
Python
Racket
Ruby
Rust
Snowball
Scala
Solidity
Spice
Swift
LLVM TableGen
Toit
TypeScript Native
V
Vala
Visual Basic
WASM
Zig
Javascript
GIMPLE
c++ source #1
Output
Compile to binary object
Link to binary
Execute the code
Intel asm syntax
Demangle identifiers
Verbose demangling
Filters
Unused labels
Library functions
Directives
Comments
Horizontal whitespace
Debug intrinsics
Compiler
6502-c++ 11.1.0
ARM GCC 10.2.0
ARM GCC 10.3.0
ARM GCC 10.4.0
ARM GCC 10.5.0
ARM GCC 11.1.0
ARM GCC 11.2.0
ARM GCC 11.3.0
ARM GCC 11.4.0
ARM GCC 12.1.0
ARM GCC 12.2.0
ARM GCC 12.3.0
ARM GCC 12.4.0
ARM GCC 13.1.0
ARM GCC 13.2.0
ARM GCC 13.2.0 (unknown-eabi)
ARM GCC 13.3.0
ARM GCC 13.3.0 (unknown-eabi)
ARM GCC 14.1.0
ARM GCC 14.1.0 (unknown-eabi)
ARM GCC 14.2.0
ARM GCC 14.2.0 (unknown-eabi)
ARM GCC 4.5.4
ARM GCC 4.6.4
ARM GCC 5.4
ARM GCC 6.3.0
ARM GCC 6.4.0
ARM GCC 7.3.0
ARM GCC 7.5.0
ARM GCC 8.2.0
ARM GCC 8.5.0
ARM GCC 9.3.0
ARM GCC 9.4.0
ARM GCC 9.5.0
ARM GCC trunk
ARM gcc 10.2.1 (none)
ARM gcc 10.3.1 (2021.07 none)
ARM gcc 10.3.1 (2021.10 none)
ARM gcc 11.2.1 (none)
ARM gcc 5.4.1 (none)
ARM gcc 7.2.1 (none)
ARM gcc 8.2 (WinCE)
ARM gcc 8.3.1 (none)
ARM gcc 9.2.1 (none)
ARM msvc v19.0 (WINE)
ARM msvc v19.10 (WINE)
ARM msvc v19.14 (WINE)
ARM64 Morello gcc 10.1 Alpha 2
ARM64 gcc 10.2
ARM64 gcc 10.3
ARM64 gcc 10.4
ARM64 gcc 10.5.0
ARM64 gcc 11.1
ARM64 gcc 11.2
ARM64 gcc 11.3
ARM64 gcc 11.4.0
ARM64 gcc 12.1
ARM64 gcc 12.2.0
ARM64 gcc 12.3.0
ARM64 gcc 12.4.0
ARM64 gcc 13.1.0
ARM64 gcc 13.2.0
ARM64 gcc 13.3.0
ARM64 gcc 14.1.0
ARM64 gcc 14.2.0
ARM64 gcc 4.9.4
ARM64 gcc 5.4
ARM64 gcc 5.5.0
ARM64 gcc 6.3
ARM64 gcc 6.4
ARM64 gcc 7.3
ARM64 gcc 7.5
ARM64 gcc 8.2
ARM64 gcc 8.5
ARM64 gcc 9.3
ARM64 gcc 9.4
ARM64 gcc 9.5
ARM64 gcc trunk
ARM64 msvc v19.14 (WINE)
AVR gcc 10.3.0
AVR gcc 11.1.0
AVR gcc 12.1.0
AVR gcc 12.2.0
AVR gcc 12.3.0
AVR gcc 12.4.0
AVR gcc 13.1.0
AVR gcc 13.2.0
AVR gcc 13.3.0
AVR gcc 14.1.0
AVR gcc 14.2.0
AVR gcc 4.5.4
AVR gcc 4.6.4
AVR gcc 5.4.0
AVR gcc 9.2.0
AVR gcc 9.3.0
Arduino Mega (1.8.9)
Arduino Uno (1.8.9)
BPF clang (trunk)
BPF clang 13.0.0
BPF clang 14.0.0
BPF clang 15.0.0
BPF clang 16.0.0
BPF clang 17.0.1
BPF clang 18.1.0
BPF clang 19.1.0
BPF gcc 13.1.0
BPF gcc 13.2.0
BPF gcc 13.3.0
BPF gcc trunk
EDG (experimental reflection)
EDG 6.5
EDG 6.5 (GNU mode gcc 13)
EDG 6.6
EDG 6.6 (GNU mode gcc 13)
FRC 2019
FRC 2020
FRC 2023
HPPA gcc 14.2.0
KVX ACB 4.1.0 (GCC 7.5.0)
KVX ACB 4.1.0-cd1 (GCC 7.5.0)
KVX ACB 4.10.0 (GCC 10.3.1)
KVX ACB 4.11.1 (GCC 10.3.1)
KVX ACB 4.12.0 (GCC 11.3.0)
KVX ACB 4.2.0 (GCC 7.5.0)
KVX ACB 4.3.0 (GCC 7.5.0)
KVX ACB 4.4.0 (GCC 7.5.0)
KVX ACB 4.6.0 (GCC 9.4.1)
KVX ACB 4.8.0 (GCC 9.4.1)
KVX ACB 4.9.0 (GCC 9.4.1)
KVX ACB 5.0.0 (GCC 12.2.1)
LoongArch64 clang (trunk)
LoongArch64 clang 17.0.1
LoongArch64 clang 18.1.0
LoongArch64 clang 19.1.0
M68K gcc 13.1.0
M68K gcc 13.2.0
M68K gcc 13.3.0
M68K gcc 14.1.0
M68K gcc 14.2.0
M68k clang (trunk)
MRISC32 gcc (trunk)
MSP430 gcc 4.5.3
MSP430 gcc 5.3.0
MSP430 gcc 6.2.1
MinGW clang 14.0.3
MinGW clang 14.0.6
MinGW clang 15.0.7
MinGW clang 16.0.0
MinGW clang 16.0.2
MinGW gcc 11.3.0
MinGW gcc 12.1.0
MinGW gcc 12.2.0
MinGW gcc 13.1.0
RISC-V (32-bits) gcc (trunk)
RISC-V (32-bits) gcc 10.2.0
RISC-V (32-bits) gcc 10.3.0
RISC-V (32-bits) gcc 11.2.0
RISC-V (32-bits) gcc 11.3.0
RISC-V (32-bits) gcc 11.4.0
RISC-V (32-bits) gcc 12.1.0
RISC-V (32-bits) gcc 12.2.0
RISC-V (32-bits) gcc 12.3.0
RISC-V (32-bits) gcc 12.4.0
RISC-V (32-bits) gcc 13.1.0
RISC-V (32-bits) gcc 13.2.0
RISC-V (32-bits) gcc 13.3.0
RISC-V (32-bits) gcc 14.1.0
RISC-V (32-bits) gcc 14.2.0
RISC-V (32-bits) gcc 8.2.0
RISC-V (32-bits) gcc 8.5.0
RISC-V (32-bits) gcc 9.4.0
RISC-V (64-bits) gcc (trunk)
RISC-V (64-bits) gcc 10.2.0
RISC-V (64-bits) gcc 10.3.0
RISC-V (64-bits) gcc 11.2.0
RISC-V (64-bits) gcc 11.3.0
RISC-V (64-bits) gcc 11.4.0
RISC-V (64-bits) gcc 12.1.0
RISC-V (64-bits) gcc 12.2.0
RISC-V (64-bits) gcc 12.3.0
RISC-V (64-bits) gcc 12.4.0
RISC-V (64-bits) gcc 13.1.0
RISC-V (64-bits) gcc 13.2.0
RISC-V (64-bits) gcc 13.3.0
RISC-V (64-bits) gcc 14.1.0
RISC-V (64-bits) gcc 14.2.0
RISC-V (64-bits) gcc 8.2.0
RISC-V (64-bits) gcc 8.5.0
RISC-V (64-bits) gcc 9.4.0
RISC-V rv32gc clang (trunk)
RISC-V rv32gc clang 10.0.0
RISC-V rv32gc clang 10.0.1
RISC-V rv32gc clang 11.0.0
RISC-V rv32gc clang 11.0.1
RISC-V rv32gc clang 12.0.0
RISC-V rv32gc clang 12.0.1
RISC-V rv32gc clang 13.0.0
RISC-V rv32gc clang 13.0.1
RISC-V rv32gc clang 14.0.0
RISC-V rv32gc clang 15.0.0
RISC-V rv32gc clang 16.0.0
RISC-V rv32gc clang 17.0.1
RISC-V rv32gc clang 18.1.0
RISC-V rv32gc clang 19.1.0
RISC-V rv32gc clang 9.0.0
RISC-V rv32gc clang 9.0.1
RISC-V rv64gc clang (trunk)
RISC-V rv64gc clang 10.0.0
RISC-V rv64gc clang 10.0.1
RISC-V rv64gc clang 11.0.0
RISC-V rv64gc clang 11.0.1
RISC-V rv64gc clang 12.0.0
RISC-V rv64gc clang 12.0.1
RISC-V rv64gc clang 13.0.0
RISC-V rv64gc clang 13.0.1
RISC-V rv64gc clang 14.0.0
RISC-V rv64gc clang 15.0.0
RISC-V rv64gc clang 16.0.0
RISC-V rv64gc clang 17.0.1
RISC-V rv64gc clang 18.1.0
RISC-V rv64gc clang 19.1.0
RISC-V rv64gc clang 9.0.0
RISC-V rv64gc clang 9.0.1
Raspbian Buster
Raspbian Stretch
SPARC LEON gcc 12.2.0
SPARC LEON gcc 12.3.0
SPARC LEON gcc 12.4.0
SPARC LEON gcc 13.1.0
SPARC LEON gcc 13.2.0
SPARC LEON gcc 13.3.0
SPARC LEON gcc 14.1.0
SPARC LEON gcc 14.2.0
SPARC gcc 12.2.0
SPARC gcc 12.3.0
SPARC gcc 12.4.0
SPARC gcc 13.1.0
SPARC gcc 13.2.0
SPARC gcc 13.3.0
SPARC gcc 14.1.0
SPARC gcc 14.2.0
SPARC64 gcc 12.2.0
SPARC64 gcc 12.3.0
SPARC64 gcc 12.4.0
SPARC64 gcc 13.1.0
SPARC64 gcc 13.2.0
SPARC64 gcc 13.3.0
SPARC64 gcc 14.1.0
SPARC64 gcc 14.2.0
TI C6x gcc 12.2.0
TI C6x gcc 12.3.0
TI C6x gcc 12.4.0
TI C6x gcc 13.1.0
TI C6x gcc 13.2.0
TI C6x gcc 13.3.0
TI C6x gcc 14.1.0
TI C6x gcc 14.2.0
TI CL430 21.6.1
VAX gcc NetBSDELF 10.4.0
VAX gcc NetBSDELF 10.5.0 (Nov 15 03:50:22 2023)
WebAssembly clang (trunk)
Xtensa ESP32 gcc 11.2.0 (2022r1)
Xtensa ESP32 gcc 12.2.0 (20230208)
Xtensa ESP32 gcc 8.2.0 (2019r2)
Xtensa ESP32 gcc 8.2.0 (2020r1)
Xtensa ESP32 gcc 8.2.0 (2020r2)
Xtensa ESP32 gcc 8.4.0 (2020r3)
Xtensa ESP32 gcc 8.4.0 (2021r1)
Xtensa ESP32 gcc 8.4.0 (2021r2)
Xtensa ESP32-S2 gcc 11.2.0 (2022r1)
Xtensa ESP32-S2 gcc 12.2.0 (20230208)
Xtensa ESP32-S2 gcc 8.2.0 (2019r2)
Xtensa ESP32-S2 gcc 8.2.0 (2020r1)
Xtensa ESP32-S2 gcc 8.2.0 (2020r2)
Xtensa ESP32-S2 gcc 8.4.0 (2020r3)
Xtensa ESP32-S2 gcc 8.4.0 (2021r1)
Xtensa ESP32-S2 gcc 8.4.0 (2021r2)
Xtensa ESP32-S3 gcc 11.2.0 (2022r1)
Xtensa ESP32-S3 gcc 12.2.0 (20230208)
Xtensa ESP32-S3 gcc 8.4.0 (2020r3)
Xtensa ESP32-S3 gcc 8.4.0 (2021r1)
Xtensa ESP32-S3 gcc 8.4.0 (2021r2)
arm64 msvc v19.20 VS16.0
arm64 msvc v19.21 VS16.1
arm64 msvc v19.22 VS16.2
arm64 msvc v19.23 VS16.3
arm64 msvc v19.24 VS16.4
arm64 msvc v19.25 VS16.5
arm64 msvc v19.27 VS16.7
arm64 msvc v19.28 VS16.8
arm64 msvc v19.28 VS16.9
arm64 msvc v19.29 VS16.10
arm64 msvc v19.29 VS16.11
arm64 msvc v19.30 VS17.0
arm64 msvc v19.31 VS17.1
arm64 msvc v19.32 VS17.2
arm64 msvc v19.33 VS17.3
arm64 msvc v19.34 VS17.4
arm64 msvc v19.35 VS17.5
arm64 msvc v19.36 VS17.6
arm64 msvc v19.37 VS17.7
arm64 msvc v19.38 VS17.8
arm64 msvc v19.39 VS17.9
arm64 msvc v19.40 VS17.10
arm64 msvc v19.latest
armv7-a clang (trunk)
armv7-a clang 10.0.0
armv7-a clang 10.0.1
armv7-a clang 11.0.0
armv7-a clang 11.0.1
armv7-a clang 12.0.0
armv7-a clang 12.0.1
armv7-a clang 13.0.0
armv7-a clang 13.0.1
armv7-a clang 14.0.0
armv7-a clang 15.0.0
armv7-a clang 16.0.0
armv7-a clang 17.0.1
armv7-a clang 18.1.0
armv7-a clang 19.1.0
armv7-a clang 9.0.0
armv7-a clang 9.0.1
armv8-a clang (all architectural features, trunk)
armv8-a clang (trunk)
armv8-a clang 10.0.0
armv8-a clang 10.0.1
armv8-a clang 11.0.0
armv8-a clang 11.0.1
armv8-a clang 12.0.0
armv8-a clang 13.0.0
armv8-a clang 14.0.0
armv8-a clang 15.0.0
armv8-a clang 16.0.0
armv8-a clang 17.0.1
armv8-a clang 18.1.0
armv8-a clang 19.1.0
armv8-a clang 9.0.0
armv8-a clang 9.0.1
ellcc 0.1.33
ellcc 0.1.34
ellcc 2017-07-16
hexagon-clang 16.0.5
llvm-mos atari2600-3e
llvm-mos atari2600-4k
llvm-mos atari2600-common
llvm-mos atari5200-supercart
llvm-mos atari8-cart-megacart
llvm-mos atari8-cart-std
llvm-mos atari8-cart-xegs
llvm-mos atari8-common
llvm-mos atari8-dos
llvm-mos c128
llvm-mos c64
llvm-mos commodore
llvm-mos cpm65
llvm-mos cx16
llvm-mos dodo
llvm-mos eater
llvm-mos mega65
llvm-mos nes
llvm-mos nes-action53
llvm-mos nes-cnrom
llvm-mos nes-gtrom
llvm-mos nes-mmc1
llvm-mos nes-mmc3
llvm-mos nes-nrom
llvm-mos nes-unrom
llvm-mos nes-unrom-512
llvm-mos osi-c1p
llvm-mos pce
llvm-mos pce-cd
llvm-mos pce-common
llvm-mos pet
llvm-mos rp6502
llvm-mos rpc8e
llvm-mos supervision
llvm-mos vic20
loongarch64 gcc 12.2.0
loongarch64 gcc 12.3.0
loongarch64 gcc 12.4.0
loongarch64 gcc 13.1.0
loongarch64 gcc 13.2.0
loongarch64 gcc 13.3.0
loongarch64 gcc 14.1.0
loongarch64 gcc 14.2.0
mips clang 13.0.0
mips clang 14.0.0
mips clang 15.0.0
mips clang 16.0.0
mips clang 17.0.1
mips clang 18.1.0
mips clang 19.1.0
mips gcc 11.2.0
mips gcc 12.1.0
mips gcc 12.2.0
mips gcc 12.3.0
mips gcc 12.4.0
mips gcc 13.1.0
mips gcc 13.2.0
mips gcc 13.3.0
mips gcc 14.1.0
mips gcc 14.2.0
mips gcc 4.9.4
mips gcc 5.4
mips gcc 5.5.0
mips gcc 9.3.0 (codescape)
mips gcc 9.5.0
mips64 (el) gcc 12.1.0
mips64 (el) gcc 12.2.0
mips64 (el) gcc 12.3.0
mips64 (el) gcc 12.4.0
mips64 (el) gcc 13.1.0
mips64 (el) gcc 13.2.0
mips64 (el) gcc 13.3.0
mips64 (el) gcc 14.1.0
mips64 (el) gcc 14.2.0
mips64 (el) gcc 4.9.4
mips64 (el) gcc 5.4.0
mips64 (el) gcc 5.5.0
mips64 (el) gcc 9.5.0
mips64 clang 13.0.0
mips64 clang 14.0.0
mips64 clang 15.0.0
mips64 clang 16.0.0
mips64 clang 17.0.1
mips64 clang 18.1.0
mips64 clang 19.1.0
mips64 gcc 11.2.0
mips64 gcc 12.1.0
mips64 gcc 12.2.0
mips64 gcc 12.3.0
mips64 gcc 12.4.0
mips64 gcc 13.1.0
mips64 gcc 13.2.0
mips64 gcc 13.3.0
mips64 gcc 14.1.0
mips64 gcc 14.2.0
mips64 gcc 4.9.4
mips64 gcc 5.4.0
mips64 gcc 5.5.0
mips64 gcc 9.5.0
mips64el clang 13.0.0
mips64el clang 14.0.0
mips64el clang 15.0.0
mips64el clang 16.0.0
mips64el clang 17.0.1
mips64el clang 18.1.0
mips64el clang 19.1.0
mipsel clang 13.0.0
mipsel clang 14.0.0
mipsel clang 15.0.0
mipsel clang 16.0.0
mipsel clang 17.0.1
mipsel clang 18.1.0
mipsel clang 19.1.0
mipsel gcc 12.1.0
mipsel gcc 12.2.0
mipsel gcc 12.3.0
mipsel gcc 12.4.0
mipsel gcc 13.1.0
mipsel gcc 13.2.0
mipsel gcc 13.3.0
mipsel gcc 14.1.0
mipsel gcc 14.2.0
mipsel gcc 4.9.4
mipsel gcc 5.4.0
mipsel gcc 5.5.0
mipsel gcc 9.5.0
nanoMIPS gcc 6.3.0 (mtk)
power gcc 11.2.0
power gcc 12.1.0
power gcc 12.2.0
power gcc 12.3.0
power gcc 12.4.0
power gcc 13.1.0
power gcc 13.2.0
power gcc 13.3.0
power gcc 14.1.0
power gcc 14.2.0
power gcc 4.8.5
power64 AT12.0 (gcc8)
power64 AT13.0 (gcc9)
power64 gcc 11.2.0
power64 gcc 12.1.0
power64 gcc 12.2.0
power64 gcc 12.3.0
power64 gcc 12.4.0
power64 gcc 13.1.0
power64 gcc 13.2.0
power64 gcc 13.3.0
power64 gcc 14.1.0
power64 gcc 14.2.0
power64 gcc trunk
power64le AT12.0 (gcc8)
power64le AT13.0 (gcc9)
power64le clang (trunk)
power64le gcc 11.2.0
power64le gcc 12.1.0
power64le gcc 12.2.0
power64le gcc 12.3.0
power64le gcc 12.4.0
power64le gcc 13.1.0
power64le gcc 13.2.0
power64le gcc 13.3.0
power64le gcc 14.1.0
power64le gcc 14.2.0
power64le gcc 6.3.0
power64le gcc trunk
powerpc64 clang (trunk)
s390x gcc 11.2.0
s390x gcc 12.1.0
s390x gcc 12.2.0
s390x gcc 12.3.0
s390x gcc 12.4.0
s390x gcc 13.1.0
s390x gcc 13.2.0
s390x gcc 13.3.0
s390x gcc 14.1.0
s390x gcc 14.2.0
sh gcc 12.2.0
sh gcc 12.3.0
sh gcc 12.4.0
sh gcc 13.1.0
sh gcc 13.2.0
sh gcc 13.3.0
sh gcc 14.1.0
sh gcc 14.2.0
sh gcc 4.9.4
sh gcc 9.5.0
vast (trunk)
x64 msvc v19.0 (WINE)
x64 msvc v19.10 (WINE)
x64 msvc v19.14 (WINE)
x64 msvc v19.20 VS16.0
x64 msvc v19.21 VS16.1
x64 msvc v19.22 VS16.2
x64 msvc v19.23 VS16.3
x64 msvc v19.24 VS16.4
x64 msvc v19.25 VS16.5
x64 msvc v19.27 VS16.7
x64 msvc v19.28 VS16.8
x64 msvc v19.28 VS16.9
x64 msvc v19.29 VS16.10
x64 msvc v19.29 VS16.11
x64 msvc v19.30 VS17.0
x64 msvc v19.31 VS17.1
x64 msvc v19.32 VS17.2
x64 msvc v19.33 VS17.3
x64 msvc v19.34 VS17.4
x64 msvc v19.35 VS17.5
x64 msvc v19.36 VS17.6
x64 msvc v19.37 VS17.7
x64 msvc v19.38 VS17.8
x64 msvc v19.39 VS17.9
x64 msvc v19.40 VS17.10
x64 msvc v19.latest
x86 djgpp 4.9.4
x86 djgpp 5.5.0
x86 djgpp 6.4.0
x86 djgpp 7.2.0
x86 msvc v19.0 (WINE)
x86 msvc v19.10 (WINE)
x86 msvc v19.14 (WINE)
x86 msvc v19.20 VS16.0
x86 msvc v19.21 VS16.1
x86 msvc v19.22 VS16.2
x86 msvc v19.23 VS16.3
x86 msvc v19.24 VS16.4
x86 msvc v19.25 VS16.5
x86 msvc v19.27 VS16.7
x86 msvc v19.28 VS16.8
x86 msvc v19.28 VS16.9
x86 msvc v19.29 VS16.10
x86 msvc v19.29 VS16.11
x86 msvc v19.30 VS17.0
x86 msvc v19.31 VS17.1
x86 msvc v19.32 VS17.2
x86 msvc v19.33 VS17.3
x86 msvc v19.34 VS17.4
x86 msvc v19.35 VS17.5
x86 msvc v19.36 VS17.6
x86 msvc v19.37 VS17.7
x86 msvc v19.38 VS17.8
x86 msvc v19.39 VS17.9
x86 msvc v19.40 VS17.10
x86 msvc v19.latest
x86 nvc++ 22.11
x86 nvc++ 22.7
x86 nvc++ 22.9
x86 nvc++ 23.1
x86 nvc++ 23.11
x86 nvc++ 23.3
x86 nvc++ 23.5
x86 nvc++ 23.7
x86 nvc++ 23.9
x86 nvc++ 24.1
x86 nvc++ 24.3
x86 nvc++ 24.5
x86 nvc++ 24.7
x86-64 Zapcc 190308
x86-64 clang (EricWF contracts)
x86-64 clang (amd-staging)
x86-64 clang (assertions trunk)
x86-64 clang (clangir)
x86-64 clang (dascandy contracts)
x86-64 clang (experimental -Wlifetime)
x86-64 clang (experimental P1061)
x86-64 clang (experimental P1144)
x86-64 clang (experimental P1221)
x86-64 clang (experimental P2996)
x86-64 clang (experimental P3068)
x86-64 clang (experimental P3309)
x86-64 clang (experimental P3367)
x86-64 clang (experimental P3372)
x86-64 clang (experimental metaprogramming - P2632)
x86-64 clang (old concepts branch)
x86-64 clang (p1974)
x86-64 clang (pattern matching - P2688)
x86-64 clang (reflection)
x86-64 clang (resugar)
x86-64 clang (thephd.dev)
x86-64 clang (trunk)
x86-64 clang (variadic friends - P2893)
x86-64 clang (widberg)
x86-64 clang 10.0.0
x86-64 clang 10.0.0 (assertions)
x86-64 clang 10.0.1
x86-64 clang 11.0.0
x86-64 clang 11.0.0 (assertions)
x86-64 clang 11.0.1
x86-64 clang 12.0.0
x86-64 clang 12.0.0 (assertions)
x86-64 clang 12.0.1
x86-64 clang 13.0.0
x86-64 clang 13.0.0 (assertions)
x86-64 clang 13.0.1
x86-64 clang 14.0.0
x86-64 clang 14.0.0 (assertions)
x86-64 clang 15.0.0
x86-64 clang 15.0.0 (assertions)
x86-64 clang 16.0.0
x86-64 clang 16.0.0 (assertions)
x86-64 clang 17.0.1
x86-64 clang 17.0.1 (assertions)
x86-64 clang 18.1.0
x86-64 clang 18.1.0 (assertions)
x86-64 clang 19.1.0
x86-64 clang 19.1.0 (assertions)
x86-64 clang 2.6.0 (assertions)
x86-64 clang 2.7.0 (assertions)
x86-64 clang 2.8.0 (assertions)
x86-64 clang 2.9.0 (assertions)
x86-64 clang 3.0.0
x86-64 clang 3.0.0 (assertions)
x86-64 clang 3.1
x86-64 clang 3.1 (assertions)
x86-64 clang 3.2
x86-64 clang 3.2 (assertions)
x86-64 clang 3.3
x86-64 clang 3.3 (assertions)
x86-64 clang 3.4 (assertions)
x86-64 clang 3.4.1
x86-64 clang 3.5
x86-64 clang 3.5 (assertions)
x86-64 clang 3.5.1
x86-64 clang 3.5.2
x86-64 clang 3.6
x86-64 clang 3.6 (assertions)
x86-64 clang 3.7
x86-64 clang 3.7 (assertions)
x86-64 clang 3.7.1
x86-64 clang 3.8
x86-64 clang 3.8 (assertions)
x86-64 clang 3.8.1
x86-64 clang 3.9.0
x86-64 clang 3.9.0 (assertions)
x86-64 clang 3.9.1
x86-64 clang 4.0.0
x86-64 clang 4.0.0 (assertions)
x86-64 clang 4.0.1
x86-64 clang 5.0.0
x86-64 clang 5.0.0 (assertions)
x86-64 clang 5.0.1
x86-64 clang 5.0.2
x86-64 clang 6.0.0
x86-64 clang 6.0.0 (assertions)
x86-64 clang 6.0.1
x86-64 clang 7.0.0
x86-64 clang 7.0.0 (assertions)
x86-64 clang 7.0.1
x86-64 clang 7.1.0
x86-64 clang 8.0.0
x86-64 clang 8.0.0 (assertions)
x86-64 clang 8.0.1
x86-64 clang 9.0.0
x86-64 clang 9.0.0 (assertions)
x86-64 clang 9.0.1
x86-64 clang rocm-4.5.2
x86-64 clang rocm-5.0.2
x86-64 clang rocm-5.1.3
x86-64 clang rocm-5.2.3
x86-64 clang rocm-5.3.3
x86-64 clang rocm-5.7.0
x86-64 clang rocm-6.0.2
x86-64 clang rocm-6.1.2
x86-64 gcc (contract labels)
x86-64 gcc (contracts natural syntax)
x86-64 gcc (contracts)
x86-64 gcc (coroutines)
x86-64 gcc (modules)
x86-64 gcc (trunk)
x86-64 gcc 10.1
x86-64 gcc 10.2
x86-64 gcc 10.3
x86-64 gcc 10.4
x86-64 gcc 10.5
x86-64 gcc 11.1
x86-64 gcc 11.2
x86-64 gcc 11.3
x86-64 gcc 11.4
x86-64 gcc 12.1
x86-64 gcc 12.2
x86-64 gcc 12.3
x86-64 gcc 12.4
x86-64 gcc 13.1
x86-64 gcc 13.2
x86-64 gcc 13.3
x86-64 gcc 14.1
x86-64 gcc 14.2
x86-64 gcc 3.4.6
x86-64 gcc 4.0.4
x86-64 gcc 4.1.2
x86-64 gcc 4.4.7
x86-64 gcc 4.5.3
x86-64 gcc 4.6.4
x86-64 gcc 4.7.1
x86-64 gcc 4.7.2
x86-64 gcc 4.7.3
x86-64 gcc 4.7.4
x86-64 gcc 4.8.1
x86-64 gcc 4.8.2
x86-64 gcc 4.8.3
x86-64 gcc 4.8.4
x86-64 gcc 4.8.5
x86-64 gcc 4.9.0
x86-64 gcc 4.9.1
x86-64 gcc 4.9.2
x86-64 gcc 4.9.3
x86-64 gcc 4.9.4
x86-64 gcc 5.1
x86-64 gcc 5.2
x86-64 gcc 5.3
x86-64 gcc 5.4
x86-64 gcc 5.5
x86-64 gcc 6.1
x86-64 gcc 6.2
x86-64 gcc 6.3
x86-64 gcc 6.4
x86-64 gcc 6.5
x86-64 gcc 7.1
x86-64 gcc 7.2
x86-64 gcc 7.3
x86-64 gcc 7.4
x86-64 gcc 7.5
x86-64 gcc 8.1
x86-64 gcc 8.2
x86-64 gcc 8.3
x86-64 gcc 8.4
x86-64 gcc 8.5
x86-64 gcc 9.1
x86-64 gcc 9.2
x86-64 gcc 9.3
x86-64 gcc 9.4
x86-64 gcc 9.5
x86-64 icc 13.0.1
x86-64 icc 16.0.3
x86-64 icc 17.0.0
x86-64 icc 18.0.0
x86-64 icc 19.0.0
x86-64 icc 19.0.1
x86-64 icc 2021.1.2
x86-64 icc 2021.10.0
x86-64 icc 2021.2.0
x86-64 icc 2021.3.0
x86-64 icc 2021.4.0
x86-64 icc 2021.5.0
x86-64 icc 2021.6.0
x86-64 icc 2021.7.0
x86-64 icc 2021.7.1
x86-64 icc 2021.8.0
x86-64 icc 2021.9.0
x86-64 icx (latest)
x86-64 icx 2021.1.2
x86-64 icx 2021.2.0
x86-64 icx 2021.3.0
x86-64 icx 2021.4.0
x86-64 icx 2022.0.0
x86-64 icx 2022.1.0
x86-64 icx 2022.2.0
x86-64 icx 2022.2.1
x86-64 icx 2023.0.0
x86-64 icx 2023.1.0
x86-64 icx 2023.2.1
x86-64 icx 2024.0.0
x86-64 icx 2024.1.0
x86-64 icx 2024.2.0
zig c++ 0.10.0
zig c++ 0.11.0
zig c++ 0.12.0
zig c++ 0.12.1
zig c++ 0.13.0
zig c++ 0.6.0
zig c++ 0.7.0
zig c++ 0.7.1
zig c++ 0.8.0
zig c++ 0.9.0
zig c++ trunk
Options
Source code
#include <optional> #include <concepts> #include <bit> #include <stdint.h> #include <math.h> #include <cstddef> #include <cstdint> #include <string> #include <cstring> #include <source_location> #include <functional> #include <algorithm> #undef NAN #undef INFINITY #define __builtin_assume(x) if (x) {} else __builtin_unreachable() namespace sus::construct { template <class T> concept Default = std::constructible_from<T>; } namespace sus::mem { template <class T> __attribute__((const)) inline __attribute__((always_inline)) constexpr T&& forward( std::remove_reference_t<T>& t) noexcept { return static_cast<T&&>(t); } template <class T> __attribute__((const)) inline __attribute__((always_inline)) constexpr T&& forward( std::remove_reference_t<T>&& t) noexcept { static_assert(!std::is_lvalue_reference_v<T>, "Can not convert an rvalue to an lvalue with forward()."); return static_cast<T&&>(t); } } namespace sus { using ::sus::mem::forward; } namespace sus::choice_type { template <class TypeListOfMemberTypes, auto... Tags> class Choice; } namespace sus::containers { template <class T, size_t N> class Array; } namespace sus::containers { template <class T> class Slice; } namespace sus::containers { template <class T> class SliceMut; } namespace sus::containers { template <class T> class Vec; } namespace sus::fn { template <class R, class... Args> class FnOnceRef; } namespace sus::fn { template <class R, class... Args> class FnMutRef; } namespace sus::fn { template <class R, class... Args> class FnRef; } namespace sus::fn { template <class R, class... Args> class FnOnceBox; } namespace sus::fn { template <class R, class... Args> class FnMutBox; } namespace sus::fn { template <class R, class... Args> class FnBox; } namespace sus::iter { template <class Iter, class Item> class IteratorBase; } namespace sus::iter { template <class RefIterator> class ByRef; template <class InnerSizedIter, class OtherSizedIter> class Chain; template <class InnerSizedIter> class Cloned; template <class InnerSizedIter> class Copied; template <class InnerSizedIter> class Cycle; template <class InnerSizedIter> class Enumerate; template <class InnerSizedIter, class Pred> class Filter; template <class ToItem, class InnerSizedIter, class FilterMapFn> class FilterMap; template <class IntoIterable, class InnerSizedIter, class MapFn> class FlatMap; template <class EachIter, class InnerSizedIter> class Flatten; template <class InnerIter> class Fuse; template <class Item> class Generator; template <class InnerSizedIter, class InspectFn> class Inspect; template <class ToItem, class InnerSizedIter> class Map; template <class ToItem, class InnerSizedIter> class MapWhile; template <class InnerSizedIter> class Peekable; template <class InnerSizedIter> class Reverse; template <class OutType, class State, class InnerSizedIter> requires(!std::is_reference_v<State>) class Scan; template <class InnerIter> class Skip; template <class InnerIter> class SkipWhile; template <class InnerIter> class StepBy; template <class InnerIter> class Take; template <class InnerIter, class Pred> class TakeWhile; template <class... InnerIters> class Zip; template <class Iter> class IteratorRange; } namespace sus::iter { struct SizeHint; } namespace sus::ptr { template <class T> requires(!std::is_reference_v<T>) class NonNull; } namespace sus::num { struct i8; struct i16; struct i32; struct i64; struct isize; struct u8; struct u16; struct u32; struct u64; struct usize; struct uptr; struct f32; struct f64; } namespace sus::option { template <class T> class Option; } namespace sus::result { template <class T, class E> class Result; } namespace sus::tuple_type { template <class T, class... Ts> class Tuple; } namespace sus::result::__private { template <class U> struct IsResultType final : std::false_type { using ok_type = void; using err_type = void; }; template <class U, class V> struct IsResultType<::sus::result::Result<U, V>> final : std::true_type { using ok_type = U; using err_type = V; }; template <class T, class Success> concept IsResultWithSuccessType = IsResultType<T>::value && std::same_as<Success, typename IsResultType<T>::ok_type>; } namespace sus::construct { template <class ToType, class FromType> concept From = requires(FromType&& from) { { ToType::from(::sus::forward<FromType>(from)) } -> std::same_as<ToType>; }; template <class ToType, class FromType> concept TryFrom = requires(FromType&& from) { { ToType::try_from(::sus::forward<FromType>(from)) } -> ::sus::result::__private::IsResultWithSuccessType<ToType>; }; } namespace sus::construct ::__private { template <class FromType> struct IntoRef final { [[nodiscard]] constexpr IntoRef(FromType&& from) noexcept : from_(static_cast<FromType&&>(from)) {} template <std::same_as<std::decay_t<FromType>> ToType> constexpr operator ToType() && noexcept { return static_cast<ToType&&>(from_); } template <::sus::construct::From<FromType> ToType> requires(!std::same_as<std::decay_t<FromType>, ToType>) constexpr operator ToType() && noexcept { return ToType::from(static_cast<FromType&&>(from_)); } IntoRef(const IntoRef&) = delete; IntoRef& operator=(const IntoRef&) = delete; private: FromType&& from_; }; template <class FromType, size_t N> struct IntoRefArray final { [[nodiscard]] constexpr IntoRefArray(FromType (&from)[N]) noexcept : from_(from) {} template <std::same_as<FromType (&)[N]> ToType> constexpr operator ToType() && noexcept { return static_cast<ToType&&>(from_); } template <::sus::construct::From<FromType (&)[N]> ToType> requires(!std::same_as<FromType, ToType>) constexpr operator ToType() && noexcept { return ToType::template from<N>(from_); } IntoRefArray(const IntoRefArray&) = delete; IntoRefArray& operator=(const IntoRefArray&) = delete; private: FromType (&from_)[N]; }; } namespace sus::mem { template <class T> concept Copy = std::is_copy_constructible_v< std::remove_const_t<std::remove_reference_t<T>>> && (std::is_copy_assignable_v< std::remove_const_t<std::remove_reference_t<T>>> || !std::is_move_assignable_v< std::remove_const_t<std::remove_reference_t<T>>>); template <class T> concept TrivialCopy = Copy<T> && std::is_trivially_copyable_v< std::remove_const_t<std::remove_reference_t<T>>>; template <class T> concept CopyOrRef = Copy<T> || std::is_reference_v<T>; } namespace sus::mem { template <class T> concept Move = std::is_move_constructible_v< std::remove_const_t<std::remove_reference_t<T>>> && std::is_move_assignable_v<std::remove_const_t<std::remove_reference_t<T>>>; template <class T> concept MoveOrRef = Move<T> || std::is_reference_v<T>; template <class T> requires(!std::is_const_v<std::remove_reference_t<T>>) __attribute__((const)) inline __attribute__((always_inline)) constexpr decltype(auto) move(T&& t) noexcept { return static_cast<std::remove_reference_t<T>&&>(t); } template <class T> concept IsMoveRef = std::is_rvalue_reference_v<T> && !std::is_const_v<std::remove_reference_t<T>>; } namespace sus { using ::sus::mem::move; } namespace sus::construct { template <class FromType, class ToType> concept Into = ::sus::construct::From<ToType, FromType> || std::same_as<ToType, FromType>; template <class FromType> requires(::sus::mem::IsMoveRef<FromType &&> && !std::is_array_v<std::remove_reference_t<FromType>>) constexpr inline auto into(FromType&& from) noexcept { return __private::IntoRef(::sus::move(from)); } template <class FromType> requires(std::is_trivially_copy_constructible_v<FromType> && !std::is_array_v<std::remove_reference_t<FromType>>) constexpr inline auto into(const FromType& from) noexcept { return __private::IntoRef<const FromType&>(from); } template <class FromType> requires(std::is_trivially_move_constructible_v<FromType> && !std::is_const_v<std::remove_reference_t<FromType>>) constexpr inline auto into(FromType& from) noexcept { return __private::IntoRef(::sus::move(from)); } template <class FromType> requires(!std::is_array_v<FromType>) constexpr inline auto ref_into( const FromType& from) noexcept { return __private::IntoRef<const FromType&>(from); } template <class FromType> requires(!std::is_const_v<std::remove_reference_t<FromType>> && !std::is_array_v<FromType>) constexpr inline auto mref_into(FromType& from) noexcept { return __private::IntoRef<FromType&>(from); } template <class FromType> requires(!std::is_const_v<std::remove_reference_t<FromType>> && !std::is_array_v<FromType>) constexpr inline auto move_into(FromType& from) noexcept { return __private::IntoRef( static_cast<std::remove_cv_t<std::remove_reference_t<FromType>>&&>(from)); } template <class FromType> requires(std::is_rvalue_reference_v<FromType &&> && !std::is_const_v<std::remove_reference_t<FromType>> && !std::is_array_v<FromType>) constexpr inline auto move_into(FromType&& from) noexcept { return __private::IntoRef( static_cast<std::remove_cv_t<std::remove_reference_t<FromType>>&&>(from)); } template <class FromType, size_t N> constexpr inline auto array_into( FromType (&from)[N]) noexcept { return __private::IntoRefArray<FromType, N>(from); } template <class FromType, class ToType> concept TryInto = ::sus::construct::TryFrom<ToType, FromType> || std::same_as<ToType, FromType>; template <class ToType, TryInto<ToType> FromType> constexpr inline auto try_into(FromType&& from) noexcept { return ToType::try_from(::sus::forward<FromType>(from)); } } namespace sus { using ::sus::construct::array_into; using ::sus::construct::into; using ::sus::construct::move_into; using ::sus::construct::mref_into; using ::sus::construct::ref_into; using ::sus::construct::try_into; } namespace sus::fn::callable { template <class T> concept FunctionPointer = requires(T t) { { std::is_pointer_v<decltype(+t)> }; }; template <class T, class R, class... Args> concept FunctionPointerReturns = ( FunctionPointer<T> && std::convertible_to<std::invoke_result_t<T, Args...>, R> && requires (R(*p)(Args...), T t) { { p = t }; } ); template <class T, class R, class... Args> concept FunctionPointerMatches = ( FunctionPointer<T> && requires (R(*p)(Args...), T t) { { p = t }; } ); template <class T, class... Args> concept FunctionPointerWith = ( FunctionPointer<T> && requires (T t, Args&&... args) { std::invoke(t, ::sus::mem::forward<Args>(args)...); } ); namespace __private { template <class T, class R, class... Args> inline constexpr bool callable_const(R (T::*)(Args...) const) { return true; }; } template <class T, class R, class... Args> concept CallableObjectReturnsOnce = !FunctionPointer<T> && requires(T t, Args&&... args) { { std::invoke(static_cast<T&&>(t), ::sus::mem::forward<Args>(args)...) } -> std::convertible_to<R>; }; template <class T, class R, class... Args> concept CallableObjectReturnsConst = !FunctionPointer<T> && requires(const T& t, Args&&... args) { { std::invoke(t, ::sus::mem::forward<Args>(args)...) } -> std::convertible_to<R>; }; template <class T, class R, class... Args> concept CallableObjectReturnsMut = !FunctionPointer<T> && requires(T& t, Args&&... args) { { std::invoke(t, ::sus::mem::forward<Args>(args)...) } -> std::convertible_to<R>; }; template <class T> concept CallableObjectConst = __private::callable_const(&T::operator()); } namespace sus::string::__private { template <class To, class From> concept ConvertibleFrom = std::convertible_to<From, To>; template <class T, class Char> concept StreamCanReceiveString = requires(T& t, std::basic_string<Char> s) { { t << s } -> ConvertibleFrom<T&>; }; template <class Char, StreamCanReceiveString<Char> S> S& format_to_stream(S& os, const std::basic_string<Char>& s) { os << s; return os; } } namespace sus::marker { struct UnsafeFnMarker { explicit consteval UnsafeFnMarker() {} }; constexpr inline auto unsafe_fn = UnsafeFnMarker(); } namespace sus::mem::__private { constexpr inline size_t min(size_t a, size_t b) { return a < b ? a : b; } template <class T, size_t bytes> struct NoUnique { [[no_unique_address]] T x; char c[bytes]; }; template <class T, size_t bytes> struct Subclass : T { char c[bytes]; }; template <class T, size_t bytes> constexpr inline size_t data_size_finder_final_class = sizeof(T) < sizeof(NoUnique<T, bytes>) ? sizeof(T) - bytes + 1 : data_size_finder_final_class<T, bytes + 1>; template <class T> constexpr inline size_t data_size_finder_final_class<T, alignof(std::max_align_t) + 1> = size_t(-1); template <class T, size_t bytes> constexpr inline size_t data_size_finder_inheritable_class = sizeof(T) < min(sizeof(NoUnique<T, bytes>), sizeof(Subclass<T, bytes>)) ? sizeof(T) - bytes + 1 : data_size_finder_inheritable_class<T, bytes + 1>; template <class T> constexpr inline size_t data_size_finder_inheritable_class<T, alignof(std::max_align_t) + 1> = size_t(-1); template <class T, size_t bytes> constexpr inline size_t data_size_finder_union = size_t(-1); template <class T, size_t bytes = 1u, bool is_class = std::is_class_v<T>, bool is_final = std::is_final_v<T>, bool is_union = std::is_union_v<T>> constexpr inline size_t data_size_finder = sizeof(T); template <class T, size_t bytes> constexpr inline size_t data_size_finder<T, bytes, true, true, false> = data_size_finder_final_class<T, bytes>; template <class T, size_t bytes> constexpr inline size_t data_size_finder<T, bytes, true, false, false> = data_size_finder_inheritable_class<T, bytes>; template <class T, size_t bytes> constexpr inline size_t data_size_finder<T, bytes, false, false, true> = data_size_finder_union<T, bytes>; } namespace sus::mem { template <class T> requires(!std::is_reference_v<T>) __attribute__((const)) consteval inline __attribute__((always_inline)) size_t size_of() noexcept { return sizeof(T); } template <class T> requires(!std::is_reference_v<T>) __attribute__((const)) consteval inline __attribute__((always_inline)) size_t data_size_of() noexcept { static_assert(alignof(T) <= alignof(std::max_align_t), "data_size_of() does not support types with alignment greater " "than std::max_align_t."); return __private::data_size_finder<T>; } } namespace sus { using sus::mem::data_size_of; using sus::mem::size_of; } namespace sus::mem { namespace __private { template <class T> struct relocatable_tag final { static constexpr bool value(...) { return false; } static constexpr bool value(int) requires requires { requires(std::same_as<decltype(T::SusUnsafeTrivialRelocate), const bool>); } { return T::SusUnsafeTrivialRelocate; }; }; } template <class... T> concept relocate_by_memcpy = (... && (std::is_reference_v<T> || (!std::is_volatile_v<std::remove_all_extents_t<T>> && sus::mem::data_size_of<std::remove_all_extents_t<std::remove_reference_t<T>>>() != size_t(-1) && (__private::relocatable_tag<std::remove_all_extents_t<T>>::value(0) || std::is_trivially_copyable_v<std::remove_all_extents_t<T>> || (std::is_trivially_move_constructible_v<std::remove_all_extents_t<T>> && std::is_trivially_move_assignable_v<std::remove_all_extents_t<T>> && std::is_trivially_destructible_v<std::remove_all_extents_t<T>>) ) ) ) ); } namespace sus::ops { template <class T, class U = T> concept Eq = requires(const std::remove_reference_t<T>& lhs, const std::remove_reference_t<U>& rhs) { { lhs == rhs } -> std::same_as<bool>; { lhs != rhs } -> std::same_as<bool>; }; } namespace sus::mem { struct NeverValueConstructor {}; namespace __private { template <class T> struct NeverValueAccess; template <class T> struct NeverValueAccess<T&> { static constexpr bool has_field = false; }; template <class T> struct NeverValueAccess { static constexpr bool has_field = requires { std::declval<T&>()._sus_Unsafe_NeverValueIsConstructed( ::sus::marker::unsafe_fn); }; constexpr NeverValueAccess() = default; template <class... U> constexpr NeverValueAccess(U&&... v) : t_(::sus::forward<U>(v)...) {} __attribute__((pure)) constexpr inline __attribute__((always_inline)) bool is_constructed() const noexcept requires(has_field) { return t_._sus_Unsafe_NeverValueIsConstructed(::sus::marker::unsafe_fn); } constexpr inline __attribute__((always_inline)) void set_destroy_value( ::sus::marker::UnsafeFnMarker) noexcept requires(has_field) { t_._sus_Unsafe_NeverValueSetDestroyValue(::sus::marker::unsafe_fn); } __attribute__((pure)) constexpr inline __attribute__((always_inline)) const T& as_inner() const { return t_; } __attribute__((pure)) constexpr inline __attribute__((always_inline)) T& as_inner_mut() { return t_; } private: T t_{NeverValueConstructor()}; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(t_)>; }; } template <class T> concept NeverValueField = __private::NeverValueAccess<T>::has_field; } namespace sus::fn { namespace __private { struct FnBoxStorageBase; template <class F> struct SusBind; enum StorageConstructionFnOnceBoxType { StorageConstructionFnOnceBox }; enum StorageConstructionFnMutBoxType { StorageConstructionFnMutBox }; enum StorageConstructionFnBoxType { StorageConstructionFnBox }; enum FnBoxType { FnBoxPointer = 1, Storage = 2, }; } template <class R, class... CallArgs> class FnOnceBox<R(CallArgs...)> { public: template <::sus::fn::callable::FunctionPointerMatches<R, CallArgs...> F> FnOnceBox(F ptr) noexcept; template <::sus::fn::callable::CallableObjectReturnsOnce<R, CallArgs...> F> requires(std::is_member_function_pointer_v<F> || std::is_member_object_pointer_v<F>) FnOnceBox(F ptr) noexcept : FnOnceBox(__private::StorageConstructionFnOnceBox, ptr) {} template <class U, class... UArgs> requires(::sus::fn::callable::CallableObjectReturnsOnce< FnOnceBox<U, UArgs...> &&, R, CallArgs...>) FnOnceBox(FnOnceBox<U, UArgs...>&& box) noexcept : FnOnceBox<R(CallArgs...)>(__private::StorageConstructionFnOnceBox, ::sus::move(box)) {} template <class U, class... UArgs> requires(::sus::fn::callable::CallableObjectReturnsOnce< FnMutBox<U, UArgs...>, R, CallArgs...>) FnOnceBox(FnMutBox<U, UArgs...>&& box) noexcept : FnOnceBox<R(CallArgs...)>(__private::StorageConstructionFnOnceBox, ::sus::move(box)) {} template <class U, class... UArgs> requires(::sus::fn::callable::CallableObjectReturnsOnce<FnBox<U, UArgs...>, R, CallArgs...>) FnOnceBox(FnBox<U, UArgs...>&& box) noexcept : FnOnceBox<R(CallArgs...)>(__private::StorageConstructionFnOnceBox, ::sus::move(box)) {} template <::sus::fn::callable::CallableObjectReturnsOnce<R, CallArgs...> F> FnOnceBox(__private::SusBind<F>&& holder) noexcept : FnOnceBox(__private::StorageConstructionFnOnceBox, ::sus::move(holder.lambda)) {} ~FnOnceBox() noexcept; FnOnceBox(FnOnceBox&& o) noexcept; FnOnceBox& operator=(FnOnceBox&& o) noexcept; FnOnceBox(const FnOnceBox&) noexcept = delete; FnOnceBox& operator=(const FnOnceBox&) noexcept = delete; inline R operator()(CallArgs... args) && noexcept; template <::sus::fn::callable::FunctionPointerMatches<R, CallArgs...> F> constexpr static auto from(F fn) noexcept { return FnOnceBox(fn); } template <::sus::fn::callable::CallableObjectReturnsOnce<R, CallArgs...> F> requires(std::is_member_function_pointer_v<F> || std::is_member_object_pointer_v<F>) constexpr static auto from(F fn) noexcept { return FnOnceBox(fn); } template <class U, class... UArgs> requires(::sus::fn::callable::CallableObjectReturnsOnce< FnOnceBox<U, UArgs...> &&, R, CallArgs...>) constexpr static auto from(FnOnceBox<U, UArgs...>&& box) noexcept { return FnOnceBox(::sus::move(box)); } template <class U, class... UArgs> requires(::sus::fn::callable::CallableObjectReturnsOnce< FnMutBox<U, UArgs...>, R, CallArgs...>) constexpr static auto from(FnMutBox<U, UArgs...>&& box) noexcept { return FnOnceBox(::sus::move(box)); } template <class U, class... UArgs> requires(::sus::fn::callable::CallableObjectReturnsOnce<FnBox<U, UArgs...>, R, CallArgs...>) constexpr static auto from(FnBox<U, UArgs...>&& box) noexcept { return FnOnceBox(::sus::move(box)); } template <::sus::fn::callable::CallableObjectReturnsOnce<R, CallArgs...> F> constexpr static auto from(__private::SusBind<F>&& holder) noexcept { return FnOnceBox(::sus::move(holder)); } protected: template <class ConstructionType, ::sus::fn::callable::CallableObjectReturnsOnce<R, CallArgs...> F> requires(!(std::is_member_function_pointer_v<std::remove_reference_t<F>> || std::is_member_object_pointer_v<std::remove_reference_t<F>>)) FnOnceBox(ConstructionType, F&& lambda) noexcept; template <class ConstructionType, ::sus::fn::callable::CallableObjectReturnsOnce<R, CallArgs...> F> requires(std::is_member_function_pointer_v<F> || std::is_member_object_pointer_v<F>) FnOnceBox(ConstructionType, F ptr) noexcept; union { R (*fn_ptr_)(CallArgs...); __private::FnBoxStorageBase* storage_; }; __private::FnBoxType type_; private: template <class FnBoxStorage> static void make_vtable(FnBoxStorage&, __private::StorageConstructionFnOnceBoxType) noexcept; template <class FnBoxStorage> static void make_vtable(FnBoxStorage&, __private::StorageConstructionFnMutBoxType) noexcept; template <class FnBoxStorage> static void make_vtable(FnBoxStorage&, __private::StorageConstructionFnBoxType) noexcept; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(fn_ptr_), decltype(storage_), decltype(type_)>; static_assert(SusUnsafeTrivialRelocate, "Type is not trivially relocatable"); private: static_assert( std::same_as<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class> friend struct ::sus::mem::__private::NeverValueAccess; __attribute__((pure)) constexpr bool _sus_Unsafe_NeverValueIsConstructed( ::sus::marker::UnsafeFnMarker) const noexcept { static_assert( std::is_assignable_v<decltype(type_)&, decltype(static_cast<__private::FnBoxType>(0))>, "The `never_value` must be able to be assigned to the named field."); return !(type_ == static_cast<__private::FnBoxType>(0)); } constexpr void _sus_Unsafe_NeverValueSetDestroyValue( ::sus::marker::UnsafeFnMarker) noexcept { static_assert(::sus::ops::Eq<decltype(type_), decltype(static_cast<__private::FnBoxType>(0))>, "The `never_value` must be comparable to the named field."); type_ = __private::FnBoxType::FnBoxPointer; } static_assert(true); protected: explicit FnOnceBox(::sus::mem::NeverValueConstructor) noexcept : type_(static_cast<__private::FnBoxType>(0)) {} }; template <class R, class... CallArgs> class FnMutBox<R(CallArgs...)> : public FnOnceBox<R(CallArgs...)> { public: template <::sus::fn::callable::FunctionPointerMatches<R, CallArgs...> F> FnMutBox(F ptr) noexcept : FnOnceBox<R(CallArgs...)>(::sus::move(ptr)) {} template <::sus::fn::callable::CallableObjectReturnsMut<R, CallArgs...> F> requires(std::is_member_function_pointer_v<F> || std::is_member_object_pointer_v<F>) FnMutBox(F ptr) noexcept : FnOnceBox<R(CallArgs...)>(__private::StorageConstructionFnMutBox, ptr) { } template <class U, class... UArgs> requires(::sus::fn::callable::CallableObjectReturnsMut< FnMutBox<U, UArgs...>, R, CallArgs...>) FnMutBox(FnMutBox<U, UArgs...>&& box) noexcept : FnOnceBox<R(CallArgs...)>(__private::StorageConstructionFnMutBox, ::sus::move(box)) {} template <class U, class... UArgs> requires(::sus::fn::callable::CallableObjectReturnsMut<FnBox<U, UArgs...>, R, CallArgs...>) FnMutBox(FnBox<U, UArgs...>&& box) noexcept : FnOnceBox<R(CallArgs...)>(__private::StorageConstructionFnMutBox, ::sus::move(box)) {} template <::sus::fn::callable::CallableObjectReturnsMut<R, CallArgs...> F> FnMutBox(__private::SusBind<F>&& holder) noexcept : FnOnceBox<R(CallArgs...)>(__private::StorageConstructionFnMutBox, ::sus::move(holder.lambda)) {} ~FnMutBox() noexcept = default; FnMutBox(FnMutBox&&) noexcept = default; FnMutBox& operator=(FnMutBox&&) noexcept = default; FnMutBox(const FnMutBox&) noexcept = delete; FnMutBox& operator=(const FnMutBox&) noexcept = delete; inline R operator()(CallArgs... args) & noexcept; inline R operator()(CallArgs... args) && noexcept { return static_cast<FnOnceBox<R(CallArgs...)>&&>(*this)( forward<CallArgs>(args)...); } template <::sus::fn::callable::FunctionPointerMatches<R, CallArgs...> F> constexpr static auto from(F fn) noexcept { return FnMutBox(fn); } template <::sus::fn::callable::CallableObjectReturnsMut<R, CallArgs...> F> requires(std::is_member_function_pointer_v<F> || std::is_member_object_pointer_v<F>) constexpr static auto from(F fn) noexcept { return FnMutBox(fn); } template <class U, class... UArgs> requires(::sus::fn::callable::CallableObjectReturnsMut< FnMutBox<U, UArgs...>, R, CallArgs...>) constexpr static auto from(FnMutBox<U, UArgs...>&& box) noexcept { return FnMutBox(::sus::move(box)); } template <class U, class... UArgs> requires(::sus::fn::callable::CallableObjectReturnsMut<FnBox<U, UArgs...>, R, CallArgs...>) constexpr static auto from(FnBox<U, UArgs...>&& box) noexcept { return FnMutBox(::sus::move(box)); } template <::sus::fn::callable::CallableObjectReturnsMut<R, CallArgs...> F> constexpr static auto from(__private::SusBind<F>&& holder) noexcept { return FnMutBox(::sus::move(holder)); } protected: template <class ConstructionType, ::sus::fn::callable::CallableObjectReturnsMut<R, CallArgs...> F> FnMutBox(ConstructionType c, F&& lambda) noexcept : FnOnceBox<R(CallArgs...)>(c, ::sus::move(lambda)) {} private: static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = true; private: static_assert( std::same_as<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class> friend struct ::sus::mem::__private::NeverValueAccess; __attribute__((pure)) constexpr bool _sus_Unsafe_NeverValueIsConstructed( ::sus::marker::UnsafeFnMarker) const noexcept { static_assert( std::is_assignable_v<decltype(FnOnceBox<R(CallArgs...)>::type_)&, decltype(static_cast<__private::FnBoxType>(0))>, "The `never_value` must be able to be assigned to the named field."); return !(FnOnceBox<R(CallArgs...)>::type_ == static_cast<__private::FnBoxType>(0)); } constexpr void _sus_Unsafe_NeverValueSetDestroyValue( ::sus::marker::UnsafeFnMarker) noexcept { static_assert(::sus::ops::Eq<decltype(FnOnceBox<R(CallArgs...)>::type_), decltype(static_cast<__private::FnBoxType>(0))>, "The `never_value` must be comparable to the named field."); FnOnceBox<R(CallArgs...)>::type_ = __private::FnBoxType::FnBoxPointer; } static_assert(true); protected: explicit FnMutBox(::sus::mem::NeverValueConstructor c) noexcept : FnOnceBox<R(CallArgs...)>(c) {} }; template <class R, class... CallArgs> class FnBox<R(CallArgs...)> final : public FnMutBox<R(CallArgs...)> { public: template <::sus::fn::callable::FunctionPointerMatches<R, CallArgs...> F> FnBox(F ptr) noexcept : FnMutBox<R(CallArgs...)>(ptr) {} template <::sus::fn::callable::CallableObjectReturnsConst<R, CallArgs...> F> requires(std::is_member_function_pointer_v<F> || std::is_member_object_pointer_v<F>) FnBox(F ptr) noexcept : FnMutBox<R(CallArgs...)>(__private::StorageConstructionFnBox, ptr) {} template <class U, class... UArgs> requires(::sus::fn::callable::CallableObjectReturnsConst<FnBox<U, UArgs...>, R, CallArgs...>) FnBox(FnBox<U, UArgs...>&& box) noexcept : FnMutBox<R(CallArgs...)>(__private::StorageConstructionFnBox, ::sus::move(box)) {} template <::sus::fn::callable::CallableObjectReturnsConst<R, CallArgs...> F> FnBox(__private::SusBind<F>&& holder) noexcept : FnMutBox<R(CallArgs...)>(__private::StorageConstructionFnBox, ::sus::move(holder.lambda)) {} ~FnBox() noexcept = default; FnBox(FnBox&&) noexcept = default; FnBox& operator=(FnBox&&) noexcept = default; FnBox(const FnBox&) noexcept = delete; FnBox& operator=(const FnBox&) noexcept = delete; inline R operator()(CallArgs... args) const& noexcept; inline R operator()(CallArgs... args) && noexcept { return static_cast<FnOnceBox<R(CallArgs...)>&&>(*this)( forward<CallArgs>(args)...); } template <::sus::fn::callable::FunctionPointerMatches<R, CallArgs...> F> constexpr static auto from(F fn) noexcept { return FnBox(fn); } template <::sus::fn::callable::CallableObjectReturnsConst<R, CallArgs...> F> requires(std::is_member_function_pointer_v<F> || std::is_member_object_pointer_v<F>) constexpr static auto from(F fn) noexcept { return FnBox(fn); } template <class U, class... UArgs> requires(::sus::fn::callable::CallableObjectReturnsConst<FnBox<U, UArgs...>, R, CallArgs...>) constexpr static auto from(FnBox<U, UArgs...>&& box) noexcept { return FnMutBox(::sus::move(box)); } template <::sus::fn::callable::CallableObjectReturnsConst<R, CallArgs...> F> constexpr static auto from(__private::SusBind<F>&& holder) noexcept { return FnBox(::sus::move(holder)); } private: template <::sus::fn::callable::CallableObjectReturnsConst<R, CallArgs...> F> FnBox(__private::StorageConstructionFnBoxType, F&& fn) noexcept; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = true; private: static_assert( std::same_as<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class> friend struct ::sus::mem::__private::NeverValueAccess; __attribute__((pure)) constexpr bool _sus_Unsafe_NeverValueIsConstructed( ::sus::marker::UnsafeFnMarker) const noexcept { static_assert( std::is_assignable_v<decltype(FnOnceBox<R(CallArgs...)>::type_)&, decltype(static_cast<__private::FnBoxType>(0))>, "The `never_value` must be able to be assigned to the named field."); return !(FnOnceBox<R(CallArgs...)>::type_ == static_cast<__private::FnBoxType>(0)); } constexpr void _sus_Unsafe_NeverValueSetDestroyValue( ::sus::marker::UnsafeFnMarker) noexcept { static_assert(::sus::ops::Eq<decltype(FnOnceBox<R(CallArgs...)>::type_), decltype(static_cast<__private::FnBoxType>(0))>, "The `never_value` must be comparable to the named field."); FnOnceBox<R(CallArgs...)>::type_ = __private::FnBoxType::FnBoxPointer; } static_assert(true); explicit FnBox(::sus::mem::NeverValueConstructor c) noexcept : FnMutBox<R(CallArgs...)>(c) {} }; } namespace sus::fn::__private { template <class F> struct SusBind final { constexpr inline SusBind(F&& lambda) : lambda(::sus::move(lambda)) {} F lambda; }; template <class T> struct UnsafePointer; template <class T> struct UnsafePointer<T*> final { constexpr inline UnsafePointer(::sus::marker::UnsafeFnMarker, T* pointer) : pointer(pointer) {} T* pointer; }; template <class T> UnsafePointer(::sus::marker::UnsafeFnMarker, T*) -> UnsafePointer<T*>; template <class T> auto make_storage(T&& t) { return std::decay_t<T>(forward<T>(t)); } template <class T> auto make_storage(T*) { static_assert(!std::is_pointer_v<T*>, "Can not store a pointer in sus_bind() except through " "sus_unsafe_pointer()."); } template <class T> auto make_storage(UnsafePointer<T*> p) { return static_cast<const T*>(p.pointer); } template <class T> auto make_storage_mut(T&& t) { return std::decay_t<T>(forward<T>(t)); } template <class T> auto make_storage_mut(T* t) { make_storage(t); } template <class T> auto make_storage_mut(UnsafePointer<T*> p) { return p.pointer; } template <class T> std::true_type is_lvalue(T&); std::false_type is_lvalue(...); template <bool = true> struct CheckCallableObjectConst final { template <class U> static constexpr inline auto error() {} }; template <> struct CheckCallableObjectConst<false> final { template <class U> static consteval inline auto error() { throw "Use sus_bind_mut() to bind a mutable lambda"; } }; } namespace sus::assertions { namespace __private { void print_panic_message(const char& msg, const std::source_location& location); void print_panic_location(const std::source_location& location); } [[noreturn]] inline void panic( const std::source_location location = std::source_location::current()) noexcept { __private::print_panic_location(location); abort(); } [[noreturn]] inline void panic_with_message( const char& msg, const std::source_location location = std::source_location::current()) noexcept { __private::print_panic_message(msg, location); abort(); } } namespace sus { using ::sus::assertions::panic; using ::sus::assertions::panic_with_message; } namespace sus::assertions { constexpr inline __attribute__((always_inline)) void check( bool cond, const std::source_location location = std::source_location::current()) { if (!cond) [[unlikely]] ::sus::panic(location); } constexpr inline __attribute__((always_inline)) void check_with_message( bool cond, const char& msg, const std::source_location location = std::source_location::current()) { if (!cond) [[unlikely]] ::sus::panic_with_message(msg, location); } } namespace sus { using ::sus::assertions::check; using ::sus::assertions::check_with_message; } namespace sus::assertions { [[noreturn]] inline __attribute__((always_inline)) void unreachable( const std::source_location location = std::source_location::current()) { panic(location); } [[noreturn]] inline __attribute__((always_inline)) void unreachable_unchecked( ::sus::marker::UnsafeFnMarker) { __builtin_unreachable(); } } namespace sus { using sus::assertions::unreachable; using sus::assertions::unreachable_unchecked; } namespace sus::fn { struct Anything; } namespace sus::fn::__private { struct NoOverloadMatchesArguments {}; template <class T> concept InvalidFunctionSignature = false; template <class... Ts> struct ArgsPack; template <class R, class... A> struct Sig { static_assert( InvalidFunctionSignature<R>, "expected a function signature of the form `ReturnType(Args...)`"); }; template <class R, class... A> struct Sig<R(A...)> { using Return = R; using Args = ArgsPack<A...>; }; template <class F, class ArgsPack> struct InvokedFnOnce { static NoOverloadMatchesArguments returns(); }; template <class F, class... Ts> requires requires(F&& f) { { std::invoke(::sus::forward<F>(f), std::declval<Ts>()...) }; } struct InvokedFnOnce<F, ArgsPack<Ts...>> { static std::invoke_result_t<F&&, Ts...> returns(); }; template <class F, class ArgsPack> struct InvokedFnMut { static NoOverloadMatchesArguments returns(); }; template <class F, class... Ts> requires requires(F f) { { std::invoke(f, std::declval<Ts>()...) }; } struct InvokedFnMut<F, ArgsPack<Ts...>> { static std::invoke_result_t<F, Ts...> returns(); }; template <class F, class ArgsPack> struct InvokedFn { static NoOverloadMatchesArguments returns(); }; template <class F, class... Ts> requires requires(const F& f) { { std::invoke(f, std::declval<Ts>()...) }; } struct InvokedFn<F, ArgsPack<Ts...>> { static std::invoke_result_t<const F&, Ts...> returns(); }; template <class ReturnType, class T> concept ValidReturnType = !std::same_as<ReturnType, NoOverloadMatchesArguments> && (std::same_as<::sus::fn::Anything, T> || std::convertible_to<ReturnType, T>); } namespace sus::fn { struct NonVoid { template <class T> constexpr NonVoid(T&&) noexcept {} }; struct Anything { template <class T> constexpr Anything(T&&) noexcept {} }; template <class F, class... S> concept FnOnce = requires { { __private::InvokedFnOnce<F, typename __private::Sig<S...>::Args>::returns() } -> __private::ValidReturnType<typename __private::Sig<S...>::Return>; }; template <class F, class... S> concept FnMut = requires { { __private::InvokedFnMut<F, typename __private::Sig<S...>::Args>::returns() } -> __private::ValidReturnType<typename __private::Sig<S...>::Return>; requires FnOnce<F, S...>; }; template <class F, class... S> concept Fn = requires { { __private::InvokedFn<F, typename __private::Sig<S...>::Args>::returns() } -> __private::ValidReturnType<typename __private::Sig<S...>::Return>; requires FnMut<F, S...>; requires FnOnce<F, S...>; }; template <class F, class... Args> requires(::sus::mem::IsMoveRef<F &&>) inline __attribute__((always_inline)) constexpr decltype(auto) call_once(F&& f, Args&&... args) { return std::invoke(sus::move(f), sus::forward<Args>(args)...); } template <class F, class... Args> requires(!std::is_const_v<std::remove_reference_t<F>>) inline __attribute__((always_inline)) constexpr decltype(auto) call_mut(F&& f, Args&&... args) { return std::invoke(static_cast<std::remove_reference_t<F>&>(f), sus::forward<Args>(args)...); } template <class F, class... Args> inline __attribute__((always_inline)) constexpr decltype(auto) call(F&& f, Args&&... args) { return std::invoke(static_cast<const std::remove_reference_t<F>&>(f), sus::forward<Args>(args)...); } } namespace sus::ptr { template <class T, class U> concept SameOrSubclassOf = std::is_pointer_v<T> && std::is_pointer_v<U> && std::is_convertible_v<T, U>; } namespace sus::iter { template <class T, class Item> concept Iterator = requires(T& t, const T& c) { requires(!std::is_void_v<typename std::decay_t<T>::Item>); requires(std::same_as<typename std::decay_t<T>::Item, Item>); requires ::sus::ptr::SameOrSubclassOf< std::decay_t<T>*, IteratorBase<std::decay_t<T>, Item>*>; { t.next() } noexcept -> std::same_as<::sus::option::Option<Item>>; { c.size_hint() } noexcept -> std::same_as<SizeHint>; }; template <class T, class Item> concept DoubleEndedIterator = Iterator<T, Item> && requires(T& t) { { t.next_back() } noexcept -> std::same_as<::sus::option::Option<Item>>; }; template <class T, class Item> concept ExactSizeIterator = Iterator<T, Item> && requires(const T& t) { { t.exact_size_hint() } noexcept -> std::same_as<::sus::num::usize>; }; } namespace sus::iter { template <class T, class Item> concept IntoIterator = requires(std::remove_cvref_t<T> t) { { ::sus::move(t).into_iter() } -> Iterator<Item>; }; template <class T> concept IntoIteratorAny = requires(std::remove_cvref_t<T> t) { { ::sus::move(t).into_iter() } -> Iterator< typename std::decay_t<decltype(::sus::move(t).into_iter())>::Item>; }; template <class T> requires(IntoIteratorAny<T>) using IntoIteratorOutputType = std::decay_t< decltype(std::declval<std::remove_cvref_t<T>&&>().into_iter())>; } namespace sus::iter::__private { template <class T> struct IntoIteratorArchetype { template <class Item> struct Iter final : public IteratorBase<Iter<Item>, Item> { ::sus::option::Option<Item> next() noexcept; SizeHint size_hint() const noexcept; }; Iter<T> into_iter() && { return Iter<T>(); } }; } namespace sus::iter { template <class ToType> struct FromIteratorImpl; template <class ToType, class ItemType> concept FromIterator = requires(__private::IntoIteratorArchetype<ItemType>&& from) { { FromIteratorImpl<ToType>::from_iter(::sus::move(from)) } -> std::same_as<ToType>; }; template <class ToType, ::sus::iter::IntoIteratorAny IntoIter> requires( FromIterator<ToType, typename IntoIteratorOutputType<IntoIter>::Item>) constexpr inline ToType from_iter(IntoIter&& into_iter) noexcept { return FromIteratorImpl<ToType>::from_iter( ::sus::move(into_iter).into_iter()); } } namespace sus::iter::__private { template <class Item> struct IteratorArchetype final : public ::sus::iter::IteratorBase<IteratorArchetype<Item>, Item> { ::sus::option::Option<Item> next() noexcept; SizeHint size_hint() const noexcept; }; } namespace sus::iter { template <class T, class Item = T> concept Product = requires(__private::IteratorArchetype<Item>&& iter) { requires(!std::is_reference_v<T>); { T::from_product(::sus::move(iter)) } -> std::same_as<T>; }; } namespace sus::iter { template <class T, class Item = T> concept Sum = requires(__private::IteratorArchetype<Item>&& iter) { requires(!std::is_reference_v<T>); { T::from_sum(::sus::move(iter)) } -> std::same_as<T>; }; } namespace sus::mem::__private { template <class T> concept IsTrivialDtorOrRef = std::is_trivially_destructible_v<T> || std::is_reference_v<T>; template <class T> concept IsTrivialCopyCtorOrRef = std::is_trivially_copy_constructible_v<T> || std::is_reference_v<T>; template <class T> concept IsTrivialCopyAssignOrRef = std::is_trivially_copy_assignable_v<T> || std::is_reference_v<T>; template <class T> concept IsTrivialMoveCtorOrRef = std::is_trivially_move_constructible_v<T> || std::is_reference_v<T>; template <class T> concept IsTrivialMoveAssignOrRef = std::is_trivially_move_assignable_v<T> || std::is_reference_v<T>; } namespace sus::mem { namespace __private { template <class T> concept HasCloneMethod = requires(const T& source) { { source.clone() } -> std::same_as<T>; }; template <class T> concept HasCloneFromMethod = requires(T& self, const T& source) { { self.clone_from(source) } -> std::same_as<void>; }; } template <class T> concept Clone = (Copy<T> && !__private::HasCloneMethod< std::remove_const_t<std::remove_reference_t<T>>>) || (!Copy<T> && Move<T> && __private::HasCloneMethod< std::remove_const_t<std::remove_reference_t<T>>>); template <class T> concept CloneOrRef = Clone<T> || std::is_reference_v<T>; template <class T> concept CloneInto = Clone<T> && ((Copy<T> && !__private::HasCloneFromMethod< std::remove_const_t<std::remove_reference_t<T>>>) || (!Copy<T> && __private::HasCloneFromMethod< std::remove_const_t<std::remove_reference_t<T>>>)); template <Clone T> [[nodiscard]] inline __attribute__((always_inline)) constexpr std::decay_t<T> clone( const T& source) noexcept { if constexpr (Copy<T>) { return source; } else { return source.clone(); } } template <CloneOrRef T> [[nodiscard]] inline __attribute__((always_inline)) constexpr T clone_or_forward( const std::remove_reference_t<T>& source) noexcept { if constexpr (std::is_reference_v<T>) { return source; } else { return ::sus::mem::clone(source); } } template <Clone T> inline __attribute__((always_inline)) constexpr void clone_into(T& dest, const T& source) noexcept { if constexpr (Copy<T>) { dest = source; } else if constexpr (__private::HasCloneFromMethod<T>) { dest.clone_from(source); } else { dest = source.clone(); } } } namespace sus { using ::sus::mem::clone; using ::sus::mem::clone_into; } namespace sus::mem { template <class T> __attribute__((const)) constexpr T* addressof(T& arg) noexcept { return __builtin_addressof(arg); } template <class T> T* addressof(T&& arg) = delete; } namespace sus::mem { template <class T, std::convertible_to<T> U> requires(!std::is_array_v<T> && ::sus::mem::Move<T> && !std::is_const_v<T> && (!std::same_as<T, U> || ::sus::mem::Copy<T>)) [[nodiscard]] inline constexpr T replace(T& dest, const U& src) noexcept { auto old = T(::sus::move(dest)); const T& typed_src = src; dest = typed_src; return old; } template <class T, std::convertible_to<T> U> requires(!std::is_array_v<T> && ::sus::mem::Move<T> && !std::is_const_v<T> && ::sus::mem::IsMoveRef<U &&>) [[nodiscard]] inline constexpr T replace(T& dest, U&& src) noexcept { auto old = T(::sus::move(dest)); T&& typed_src = ::sus::move(src); dest = ::sus::move(typed_src); return old; } } namespace sus::mem { template <class T> requires(::sus::mem::Move<T> && ::sus::construct::Default<T> && std::is_final_v<T>) inline constexpr T take(T& t) noexcept { auto taken = T(::sus::move(t)); t.~T(); std::construct_at(&t); return taken; } template <class T> requires(::sus::mem::Move<T>) inline constexpr T take_and_destruct(::sus::marker::UnsafeFnMarker, T& t) noexcept { auto taken = T(static_cast<T&&>(t)); t.~T(); return taken; } template <class T> requires(::sus::mem::Copy<T>) inline constexpr T take_copy_and_destruct(::sus::marker::UnsafeFnMarker, const T& t) noexcept { auto taken = T(t); t.~T(); return taken; } } namespace sus::fn::__private { template <class F, class R, class... Args> concept FunctionPointer = std::is_pointer_v<std::decay_t<F>> && requires(F f, Args... args) { { std::invoke(*f, args...) } -> std::convertible_to<R>; }; template <class T> concept IsFunctionPointer = std::is_pointer_v<T> && std::is_function_v<std::remove_pointer_t<T>>; template <class F> concept ConvertsToFunctionPointer = requires(F f) { { +f } -> IsFunctionPointer; }; template <class F, class R, class... Args> concept CallableOnceMut = !FunctionPointer<F, R, Args...> && requires(F&& f, Args... args) { { std::invoke(::sus::move(f), ::sus::forward<Args>(args)...) } -> std::convertible_to<R>; }; template <class F, class R, class... Args> concept CallableMut = !FunctionPointer<F, R, Args...> && requires(F& f, Args... args) { { std::invoke(f, ::sus::forward<Args>(args)...) } -> std::convertible_to<R>; }; template <class F, class R, class... Args> concept CallableConst = !FunctionPointer<F, R, Args...> && requires(const F& f, Args... args) { { std::invoke(f, ::sus::forward<Args>(args)...) } -> std::convertible_to<R>; }; } namespace sus::fn::__private { union Storage { void (*fnptr)(); void* object; }; template <class F> struct Invoker { template <class R, class... Args> static R fnptr_call_mut(const union Storage& s, Args... args) { F f = reinterpret_cast<F>(s.fnptr); return std::invoke(*f, ::sus::forward<Args>(args)...); } template <class R, class... Args> static R object_call_mut(const union Storage& s, Args... args) { F& f = *static_cast<F*>(s.object); return std::invoke(f, ::sus::forward<Args>(args)...); } template <class R, class... Args> static R object_call_once(const union Storage& s, Args... args) { F& f = *static_cast<F*>(s.object); return std::invoke(::sus::move(f), ::sus::forward<Args>(args)...); } template <class R, class... Args> static R fnptr_call_const(const union Storage& s, Args... args) { const F f = reinterpret_cast<const F>(s.fnptr); return std::invoke(*f, ::sus::forward<Args>(args)...); } template <class R, class... Args> static R object_call_const(const union Storage& s, Args... args) { const F& f = *static_cast<const F*>(s.object); return std::invoke(f, ::sus::forward<Args>(args)...); } }; template <class R, class... CallArgs> using InvokeFnPtr = R (*)(const union Storage& s, CallArgs... args); } namespace sus::fn { template <class R, class... CallArgs> class FnRef<R(CallArgs...)> { public: template <__private::FunctionPointer<R, CallArgs...> F> FnRef(F ptr) noexcept { ::sus::check(ptr != nullptr); storage_.fnptr = reinterpret_cast<void (*)()>(ptr); invoke_ = &__private::Invoker<F>::template fnptr_call_const<R, CallArgs...>; } template <__private::CallableConst<R, CallArgs...> F> requires(__private::ConvertsToFunctionPointer<F>) constexpr FnRef(F&& object) noexcept { storage_.object = ::sus::mem::addressof(object); invoke_ = &__private::Invoker< std::remove_reference_t<F>>::template object_call_const<R, CallArgs...>; } template <__private::CallableConst<R, CallArgs...> F> requires(!__private::ConvertsToFunctionPointer<F>) constexpr FnRef(F&& object) noexcept { storage_.object = ::sus::mem::addressof(object); invoke_ = &__private::Invoker< std::remove_reference_t<F>>::template object_call_const<R, CallArgs...>; } ~FnRef() noexcept = default; constexpr FnRef(FnRef&& o) noexcept : storage_(o.storage_), invoke_(::sus::mem::replace(o.invoke_, nullptr)) { ::sus::check(invoke_); } constexpr FnRef& operator=(FnRef&& o) noexcept { storage_ = o.storage_; invoke_ = ::sus::mem::replace(o.invoke_, nullptr); ::sus::check(invoke_); return *this; } FnRef(const FnRef&) noexcept = delete; FnRef& operator=(const FnRef&) noexcept = delete; constexpr FnRef clone() const { ::sus::check(invoke_); return FnRef(storage_, invoke_); } inline R operator()(CallArgs... args) const& { ::sus::check(invoke_); return (*invoke_)(storage_, ::sus::forward<CallArgs>(args)...); } inline R operator()(CallArgs... args) && { ::sus::check(invoke_); return (*::sus::mem::replace(invoke_, nullptr))( storage_, ::sus::forward<CallArgs>(args)...); } constexpr static auto from( __private::FunctionPointer<R, CallArgs...> auto ptr) noexcept { return FnRef(ptr); } template <__private::CallableConst<R, CallArgs...> F> constexpr static auto from(F&& object) noexcept { return FnRef(::sus::forward<F>(object)); } private: template <class RR, class... AArgs> friend class FnOnceRef; template <class RR, class... AArgs> friend class FnMutRef; constexpr FnRef(union __private::Storage storage, __private::InvokeFnPtr<R, CallArgs...> invoke) : storage_(storage), invoke_(invoke) {} union __private::Storage storage_; __private::InvokeFnPtr<R, CallArgs...> invoke_; static R invoke_never_value(const union __private::Storage& s, CallArgs... args) {} static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(storage_.fnptr), decltype(storage_.object), decltype(invoke_)>; static_assert(SusUnsafeTrivialRelocate, "Type is not trivially relocatable"); private: static_assert( std::same_as<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class> friend struct ::sus::mem::__private::NeverValueAccess; __attribute__((pure)) constexpr bool _sus_Unsafe_NeverValueIsConstructed( ::sus::marker::UnsafeFnMarker) const noexcept { static_assert( std::is_assignable_v<decltype(invoke_)&, decltype(&invoke_never_value)>, "The `never_value` must be able to be assigned to the named field."); return !(invoke_ == &invoke_never_value); } constexpr void _sus_Unsafe_NeverValueSetDestroyValue( ::sus::marker::UnsafeFnMarker) noexcept { static_assert(::sus::ops::Eq<decltype(invoke_), decltype(&invoke_never_value)>, "The `never_value` must be comparable to the named field."); invoke_ = &invoke_never_value; } static_assert(true); explicit constexpr FnRef(::sus::mem::NeverValueConstructor) noexcept : invoke_(&invoke_never_value) {} }; template <class R, class... CallArgs> class FnMutRef<R(CallArgs...)> { public: template <__private::FunctionPointer<R, CallArgs...> F> FnMutRef(F ptr) noexcept { ::sus::check(ptr != nullptr); storage_.fnptr = reinterpret_cast<void (*)()>(ptr); invoke_ = &__private::Invoker<F>::template fnptr_call_mut<R, CallArgs...>; } template <__private::CallableMut<R, CallArgs...> F> requires(__private::ConvertsToFunctionPointer<F>) constexpr FnMutRef(F&& object) noexcept { storage_.object = ::sus::mem::addressof(object); invoke_ = &__private::Invoker< std::remove_reference_t<F>>::template object_call_mut<R, CallArgs...>; } template <__private::CallableMut<R, CallArgs...> F> requires(!__private::ConvertsToFunctionPointer<F>) constexpr FnMutRef(F&& object) noexcept { storage_.object = ::sus::mem::addressof(object); invoke_ = &__private::Invoker< std::remove_reference_t<F>>::template object_call_mut<R, CallArgs...>; } constexpr FnMutRef(FnRef<R(CallArgs...)>&& o) noexcept : storage_(o.storage_), invoke_(::sus::mem::replace(o.invoke_, nullptr)) { ::sus::check(invoke_); } ~FnMutRef() noexcept = default; constexpr FnMutRef(FnMutRef&& o) noexcept : storage_(o.storage_), invoke_(::sus::mem::replace(o.invoke_, nullptr)) { ::sus::check(invoke_); } constexpr FnMutRef& operator=(FnMutRef&& o) noexcept { storage_ = o.storage_; invoke_ = ::sus::mem::replace(o.invoke_, nullptr); ::sus::check(invoke_); return *this; } FnMutRef(const FnMutRef&) noexcept = delete; FnMutRef& operator=(const FnMutRef&) noexcept = delete; constexpr FnMutRef clone() const { ::sus::check(invoke_); return FnMutRef(storage_, invoke_); } inline R operator()(CallArgs... args) & { ::sus::check(invoke_); return (*invoke_)(storage_, ::sus::forward<CallArgs>(args)...); } inline R operator()(CallArgs... args) && { ::sus::check(invoke_); return (*::sus::mem::replace(invoke_, nullptr))( storage_, ::sus::forward<CallArgs>(args)...); } constexpr static auto from( __private::FunctionPointer<R, CallArgs...> auto ptr) noexcept { return FnMutRef(ptr); } template <__private::CallableMut<R, CallArgs...> F> constexpr static auto from(F&& object) noexcept { return FnMutRef(::sus::forward<F>(object)); } private: template <class RR, class... AArgs> friend class FnOnceRef; constexpr FnMutRef(union __private::Storage storage, __private::InvokeFnPtr<R, CallArgs...> invoke) : storage_(storage), invoke_(invoke) {} union __private::Storage storage_; __private::InvokeFnPtr<R, CallArgs...> invoke_; static R invoke_never_value(const union __private::Storage& s, CallArgs... args) {} static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(storage_.fnptr), decltype(storage_.object), decltype(invoke_)>; static_assert(SusUnsafeTrivialRelocate, "Type is not trivially relocatable"); private: static_assert( std::same_as<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class> friend struct ::sus::mem::__private::NeverValueAccess; __attribute__((pure)) constexpr bool _sus_Unsafe_NeverValueIsConstructed( ::sus::marker::UnsafeFnMarker) const noexcept { static_assert( std::is_assignable_v<decltype(invoke_)&, decltype(&invoke_never_value)>, "The `never_value` must be able to be assigned to the named field."); return !(invoke_ == &invoke_never_value); } constexpr void _sus_Unsafe_NeverValueSetDestroyValue( ::sus::marker::UnsafeFnMarker) noexcept { static_assert(::sus::ops::Eq<decltype(invoke_), decltype(&invoke_never_value)>, "The `never_value` must be comparable to the named field."); invoke_ = &invoke_never_value; } static_assert(true); explicit constexpr FnMutRef(::sus::mem::NeverValueConstructor) noexcept : invoke_(&invoke_never_value) {} }; template <class R, class... CallArgs> class FnOnceRef<R(CallArgs...)> { public: template <__private::FunctionPointer<R, CallArgs...> F> FnOnceRef(F ptr) noexcept { ::sus::check(ptr != nullptr); storage_.fnptr = reinterpret_cast<void (*)()>(ptr); invoke_ = &__private::Invoker<F>::template fnptr_call_mut<R, CallArgs...>; } template <__private::CallableOnceMut<R, CallArgs...> F> requires(__private::ConvertsToFunctionPointer<F>) constexpr FnOnceRef(F&& object) noexcept { storage_.object = ::sus::mem::addressof(object); invoke_ = &__private::Invoker< std::remove_reference_t<F>>::template object_call_once<R, CallArgs...>; } template <__private::CallableOnceMut<R, CallArgs...> F> requires(!__private::ConvertsToFunctionPointer<F>) constexpr FnOnceRef(F&& object) noexcept { storage_.object = ::sus::mem::addressof(object); invoke_ = &__private::Invoker< std::remove_reference_t<F>>::template object_call_once<R, CallArgs...>; } constexpr FnOnceRef(FnMutRef<R(CallArgs...)>&& o) noexcept : storage_(o.storage_), invoke_(::sus::mem::replace(o.invoke_, nullptr)) { ::sus::check(invoke_); } constexpr FnOnceRef(FnRef<R(CallArgs...)>&& o) noexcept : storage_(o.storage_), invoke_(::sus::mem::replace(o.invoke_, nullptr)) { ::sus::check(invoke_); } ~FnOnceRef() noexcept = default; constexpr FnOnceRef(FnOnceRef&& o) noexcept : storage_(o.storage_), invoke_(::sus::mem::replace(o.invoke_, nullptr)) { ::sus::check(invoke_); } constexpr FnOnceRef& operator=(FnOnceRef&& o) noexcept { storage_ = o.storage_; invoke_ = ::sus::mem::replace(o.invoke_, nullptr); ::sus::check(invoke_); return *this; } FnOnceRef(const FnOnceRef&) noexcept = delete; FnOnceRef& operator=(const FnOnceRef&) noexcept = delete; class Split { public: Split(FnOnceRef& fn) : fn_(fn) {} Split(Split&&) = delete; Split& operator=(Split&&) = delete; R operator()(CallArgs... args) && { return ::sus::move(fn_)(::sus::forward<CallArgs>(args)...); } private: FnOnceRef& fn_; }; constexpr Split split() & noexcept { return Split(*this); } inline R operator()(CallArgs... args) && { ::sus::check(invoke_); return (*::sus::mem::replace(invoke_, nullptr))( storage_, ::sus::forward<CallArgs>(args)...); } constexpr static auto from( __private::FunctionPointer<R, CallArgs...> auto ptr) noexcept { return FnOnceRef(ptr); } template <__private::CallableOnceMut<R, CallArgs...> F> constexpr static auto from(F&& object) noexcept { return FnOnceRef(::sus::forward<F>(object)); } private: friend FnMutRef<R, CallArgs...>; friend FnRef<R, CallArgs...>; constexpr FnOnceRef(union __private::Storage storage, __private::InvokeFnPtr<R, CallArgs...> invoke) : storage_(storage), invoke_(invoke) {} union __private::Storage storage_; __private::InvokeFnPtr<R, CallArgs...> invoke_; static R invoke_never_value(const union __private::Storage& s, CallArgs... args) {} static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(storage_.fnptr), decltype(storage_.object), decltype(invoke_)>; static_assert(SusUnsafeTrivialRelocate, "Type is not trivially relocatable"); private: static_assert( std::same_as<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class> friend struct ::sus::mem::__private::NeverValueAccess; __attribute__((pure)) constexpr bool _sus_Unsafe_NeverValueIsConstructed( ::sus::marker::UnsafeFnMarker) const noexcept { static_assert( std::is_assignable_v<decltype(invoke_)&, decltype(&invoke_never_value)>, "The `never_value` must be able to be assigned to the named field."); return !(invoke_ == &invoke_never_value); } constexpr void _sus_Unsafe_NeverValueSetDestroyValue( ::sus::marker::UnsafeFnMarker) noexcept { static_assert(::sus::ops::Eq<decltype(invoke_), decltype(&invoke_never_value)>, "The `never_value` must be comparable to the named field."); invoke_ = &invoke_never_value; } static_assert(true); explicit constexpr FnOnceRef(::sus::mem::NeverValueConstructor) noexcept : invoke_(&invoke_never_value) {} }; } namespace sus::ops { template <class T> concept Ordering = (std::same_as<T, std::strong_ordering> || std::same_as<T, std::partial_ordering> || std::same_as<T, std::weak_ordering>); template <class Lhs, class Rhs = Lhs> concept Ord = requires(const std::remove_reference_t<Lhs>& lhs, const std::remove_reference_t<Rhs>& rhs) { { lhs <=> rhs } -> std::same_as<std::strong_ordering>; }; template <class Lhs, class Rhs = Lhs> concept WeakOrd = Ord<Lhs, Rhs> || requires(const std::remove_reference_t<Lhs>& lhs, const std::remove_reference_t<Rhs>& rhs) { { lhs <=> rhs } -> std::same_as<std::weak_ordering>; }; template <class Lhs, class Rhs = Lhs> concept PartialOrd = WeakOrd<Lhs, Rhs> || Ord<Lhs, Rhs> || requires(const std::remove_reference_t<Lhs>& lhs, const Rhs& rhs) { { lhs <=> rhs } -> std::same_as<std::partial_ordering>; }; template <class Lhs, class Rhs = Lhs> concept ExclusiveOrd = Ord<Lhs, Rhs>; template <class Lhs, class Rhs = Lhs> concept ExclusiveWeakOrd = (!Ord<Lhs, Rhs> && WeakOrd<Lhs, Rhs>); template <class Lhs, class Rhs = Lhs> concept ExclusivePartialOrd = (!WeakOrd<Lhs, Rhs> && PartialOrd<Lhs, Rhs>); template <class T> requires(::sus::ops::Ord<T>) inline constexpr T min(T a, T b) noexcept { return a > b ? ::sus::forward<T>(b) : ::sus::forward<T>(a); } template <class T> constexpr T min_by( T a, T b, ::sus::fn::FnOnce<std::strong_ordering( const std::remove_reference_t<T>&, const std::remove_reference_t<T>&)> auto&& compare) noexcept { return ::sus::fn::call_once(::sus::move(compare), a, b) == std::strong_ordering::greater ? ::sus::forward<T>(b) : ::sus::forward<T>(a); } template < class T, ::sus::fn::FnMut<::sus::fn::NonVoid(const std::remove_reference_t<T>&)> KeyFn, int&..., class Key = std::invoke_result_t<KeyFn&, const std::remove_reference_t<T>&>> requires(::sus::ops::Ord<Key>) constexpr T min_by_key(T a, T b, KeyFn f) noexcept { return ::sus::fn::call_mut(f, a) > ::sus::fn::call_mut(f, b) ? ::sus::forward<T>(b) : ::sus::forward<T>(a); } template <class T> requires(::sus::ops::Ord<T>) constexpr T max(T a, T b) noexcept { return a > b ? ::sus::forward<T>(a) : ::sus::forward<T>(b); } template <class T> constexpr T max_by( T a, T b, ::sus::fn::FnOnce<std::strong_ordering( const std::remove_reference_t<T>&, const std::remove_reference_t<T>&)> auto&& compare) noexcept { return ::sus::fn::call_once(::sus::move(compare), a, b) == std::strong_ordering::greater ? ::sus::forward<T>(a) : ::sus::forward<T>(b); } template < class T, ::sus::fn::FnMut<::sus::fn::NonVoid(const std::remove_reference_t<T>&)> KeyFn, int&..., class Key = std::invoke_result_t<KeyFn&, const std::remove_reference_t<T>&>> requires(::sus::ops::Ord<Key>) constexpr T max_by_key(T a, T b, KeyFn f) noexcept { return f(a) > f(b) ? ::sus::forward<T>(a) : ::sus::forward<T>(b); } template <class T> requires(::sus::ops::Ord<T>) constexpr T clamp(T v, T min, T max) noexcept { ::sus::check(min <= max); return v < min ? ::sus::forward<T>(min) : (v > max ? ::sus::forward<T>(max) : ::sus::forward<T>(v)); } } namespace sus::ops { template <class T> struct TryImpl; template <class T> concept Try = requires { requires !std::is_reference_v<T>; typename TryImpl<T>::Output; requires !std::is_reference_v<typename TryImpl<T>::Output>; requires !std::is_void_v<typename TryImpl<T>::Output>; } && requires(const T& t, T&& tt, TryImpl<T>::Output output) { { TryImpl<T>::is_success(t) } -> std::same_as<bool>; { TryImpl<T>::into_output(::sus::move(tt)) } -> std::same_as<typename TryImpl<T>::Output>; { TryImpl<T>::from_output(::sus::move(output)) } -> std::same_as<T>; }; template <Try T> constexpr inline bool try_is_success(const T& t) noexcept { return TryImpl<T>::is_success(t); } template <Try T> requires(::sus::mem::IsMoveRef<T &&>) constexpr inline TryImpl<T>::Output try_into_output(T&& t) noexcept { ::sus::check(TryImpl<T>::is_success(t)); return TryImpl<T>::into_output(::sus::move(t)); } template <Try T> constexpr inline T try_from_output(typename TryImpl<T>::Output&& t) noexcept { return TryImpl<T>::from_output(::sus::move(t)); } } namespace sus::option::__private { template <class U> struct IsOptionType final : std::false_type { using inner_type = void; }; template <class U> struct IsOptionType<Option<U>> final : std::true_type { using inner_type = U; }; } namespace sus::option::__private { template <class U> struct IsTupleOfSizeTwo final { static constexpr bool value = false; using first_type = void; using second_type = void; }; template <class U, class V> struct IsTupleOfSizeTwo<::sus::tuple_type::Tuple<U, V>> final { static constexpr bool value = true; using first_type = U; using second_type = V; }; } namespace sus::construct { namespace __private { template <class T> concept IsConstLvalueReference = std::is_lvalue_reference_v<T> && std::is_const_v<std::remove_reference_t<T>>; } template <class To, class From> concept SafelyConstructibleFromReference = !__private::IsConstLvalueReference<To> || std::same_as<std::remove_cvref_t<From>, std::remove_cvref_t<To>> || sus::ptr::SameOrSubclassOf<std::remove_cvref_t<From>*, std::remove_cvref_t<To>*>; } namespace sus::mem { namespace __private { template <class T> struct remove_rvalue_reference_helper { using type = T; }; template <class T> struct remove_rvalue_reference_helper<T&&> { using type = T; }; } template <class T> using remove_rvalue_reference = __private::remove_rvalue_reference_helper<T>::type; } namespace sus::option::__private { template <class T> struct SomeMarker { constexpr inline SomeMarker(T&& value) : value(::sus::forward<T>(value)){}; T&& value; template <class U> requires(std::constructible_from<U, const T&>) inline constexpr operator Option<U>() const& noexcept { static_assert( ::sus::construct::SafelyConstructibleFromReference<U, const T&>, "Unable to safely convert to a different reference type, as conversion " "would produce a reference to a temporary. The SomeMarker's value type " "must match the Option's. For example an `Option<const i32&>` can not " "be constructed from a SomeMarker holding `const i16&`, but it can be " "constructed from `i32&&`."); return Option<U>::with(static_cast<const T&>(value)); } template <class U> inline constexpr operator Option<U>() && noexcept { static_assert( ::sus::construct::SafelyConstructibleFromReference<U, T&&>, "Unable to safely convert to a different reference type, as conversion " "would produce a reference to a temporary. The SomeMarker's value type " "must match the Option's. For example an `Option<const i32&>` can not " "be constructed from a SomeMarker holding `const i16&`, but it can be " "constructed from `i32&&`."); return Option<U>::with(::sus::forward<T>(value)); } template <class U = ::sus::mem::remove_rvalue_reference<T>> inline constexpr Option<U> construct() && noexcept { return sus::move(*this); } }; struct NoneMarker { template <class U> __attribute__((const)) inline constexpr operator Option<U>() const& noexcept { return Option<U>(); } template <class U> __attribute__((const)) inline constexpr operator Option<U>() && noexcept { return Option<U>(); } template <class T> inline constexpr Option<T> construct() && noexcept { return sus::move(*this); } }; } namespace sus::option { enum class State : bool { None, Some, }; } namespace sus::option::__private { using State::None; using State::Some; template <class T, bool = sus::mem::NeverValueField<T>> struct Storage; template <class T> struct Storage<T, false> final { constexpr ~Storage() requires(std::is_trivially_destructible_v<T>) = default; constexpr ~Storage() requires(!std::is_trivially_destructible_v<T>) {} constexpr Storage(const Storage&) requires(std::is_trivially_copy_constructible_v<T>) = default; constexpr Storage& operator=(const Storage&) requires(std::is_trivially_copy_assignable_v<T>) = default; constexpr Storage(Storage&&) requires(std::is_trivially_move_constructible_v<T>) = default; constexpr Storage& operator=(Storage&&) requires(std::is_trivially_move_assignable_v<T>) = default; constexpr Storage(const Storage&) requires(!std::is_trivially_copy_constructible_v<T>) { sus::unreachable(); } constexpr Storage& operator=(const Storage&) requires(!std::is_trivially_copy_assignable_v<T>) { sus::unreachable(); } constexpr Storage(Storage&&) requires(!std::is_trivially_move_constructible_v<T>) { sus::unreachable(); } constexpr Storage& operator=(Storage&&) requires(!std::is_trivially_move_assignable_v<T>) { sus::unreachable(); } constexpr Storage() {} constexpr Storage(const std::remove_cvref_t<T>& t) : val_(t), state_(Some) {} constexpr Storage(std::remove_cvref_t<T>& t) : val_(t), state_(Some) {} constexpr Storage(std::remove_cvref_t<T>&& t) : val_(::sus::move(t)), state_(Some) {} __attribute__((pure)) constexpr const T& val() const { return val_; } __attribute__((pure)) constexpr T& val_mut() { return val_; } __attribute__((pure)) constexpr inline State state() const noexcept { return state_; } constexpr inline void construct_from_none(const T& t) noexcept requires(::sus::mem::Copy<T>) { std::construct_at(&val_, t); state_ = Some; } constexpr inline void construct_from_none(T&& t) noexcept { std::construct_at(&val_, ::sus::move(t)); state_ = Some; } constexpr inline void set_some(const T& t) noexcept requires(::sus::mem::Copy<T>) { if (state_ == None) construct_from_none(t); else val_ = t; state_ = Some; } constexpr inline void set_some(T&& t) noexcept { if (state_ == None) construct_from_none(::sus::move(t)); else val_ = ::sus::move(t); state_ = Some; } [[nodiscard]] constexpr inline T replace_some(T&& t) noexcept { return ::sus::mem::replace(val_, ::sus::move(t)); } [[nodiscard]] constexpr inline T take_and_set_none() noexcept { state_ = None; if constexpr (::sus::mem::Move<T>) { return ::sus::mem::take_and_destruct(::sus::marker::unsafe_fn, val_); } else { return ::sus::mem::take_copy_and_destruct(::sus::marker::unsafe_fn, val_); } } constexpr inline void set_none() noexcept { state_ = None; val_.~T(); } constexpr inline void destroy() noexcept { val_.~T(); } private: union { T val_; }; State state_ = None; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(val_)>; }; template <class T> struct Storage<T, true> final { constexpr ~Storage() requires(std::is_trivially_destructible_v<T>) = default; constexpr ~Storage() requires(!std::is_trivially_destructible_v<T>) {} constexpr Storage(const Storage&) requires(std::is_trivially_copy_constructible_v<T>) = default; constexpr Storage& operator=(const Storage&) requires(std::is_trivially_copy_assignable_v<T>) = default; constexpr Storage(Storage&&) requires(std::is_trivially_move_constructible_v<T>) = default; constexpr Storage& operator=(Storage&&) requires(std::is_trivially_move_assignable_v<T>) = default; constexpr Storage(const Storage&) requires(!std::is_trivially_copy_constructible_v<T>) { sus::unreachable(); } constexpr Storage& operator=(const Storage&) requires(!std::is_trivially_copy_assignable_v<T>) { sus::unreachable(); } constexpr Storage(Storage&&) requires(!std::is_trivially_move_constructible_v<T>) { sus::unreachable(); } constexpr Storage& operator=(Storage&&) requires(!std::is_trivially_move_assignable_v<T>) { sus::unreachable(); } constexpr Storage() : access_() {} constexpr Storage(const T& t) : access_(t) {} constexpr Storage(T&& t) : access_(::sus::move(t)) {} __attribute__((pure)) constexpr const T& val() const { return access_.as_inner(); }; __attribute__((pure)) constexpr T& val_mut() { return access_.as_inner_mut(); }; __attribute__((pure)) constexpr inline State state() const noexcept { return access_.is_constructed() ? Some : None; } constexpr inline void construct_from_none(const T& t) noexcept requires(::sus::mem::Copy<T>) { access_.set_destroy_value(::sus::marker::unsafe_fn); access_.~NeverValueAccess(); std::construct_at(&access_, t); } constexpr inline void construct_from_none(T&& t) noexcept { access_.set_destroy_value(::sus::marker::unsafe_fn); access_.~NeverValueAccess(); std::construct_at(&access_, ::sus::move(t)); } constexpr inline void set_some(const T& t) noexcept requires(::sus::mem::Copy<T>) { if (state() == None) construct_from_none(t); else access_.as_inner_mut() = t; } constexpr inline void set_some(T&& t) noexcept { if (state() == None) construct_from_none(::sus::move(t)); else access_.as_inner_mut() = ::sus::move(t); } [[nodiscard]] constexpr inline T replace_some(T&& t) noexcept { return ::sus::mem::replace(access_.as_inner_mut(), ::sus::move(t)); } [[nodiscard]] constexpr inline T take_and_set_none() noexcept { auto t = T(::sus::move(access_.as_inner_mut())); access_.~NeverValueAccess(); std::construct_at(&access_); return t; } constexpr inline void set_none() noexcept { access_.~NeverValueAccess(); std::construct_at(&access_); } constexpr inline void destroy() noexcept { if (!access_.is_constructed()) access_.set_destroy_value(::sus::marker::unsafe_fn); access_.~NeverValueAccess(); } private: using NeverValueAccess = ::sus::mem::__private::NeverValueAccess<T>; union { NeverValueAccess access_; }; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(access_)>; }; template <class T> struct StoragePointer {}; template <class T> struct StoragePointer<T&> { explicit constexpr inline __attribute__((always_inline)) StoragePointer(T& ref) noexcept : ptr_(::sus::mem::addressof(ref)) {} inline constexpr operator const T&() const { return *ptr_; } inline constexpr operator T&() { return *ptr_; } private: T* ptr_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(ptr_)>; static_assert(SusUnsafeTrivialRelocate, "Type is not trivially relocatable"); private: static_assert( std::same_as<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class> friend struct ::sus::mem::__private::NeverValueAccess; __attribute__((pure)) constexpr bool _sus_Unsafe_NeverValueIsConstructed( ::sus::marker::UnsafeFnMarker) const noexcept { static_assert( std::is_assignable_v<decltype(ptr_)&, decltype(nullptr)>, "The `never_value` must be able to be assigned to the named field."); return !(ptr_ == nullptr); } constexpr void _sus_Unsafe_NeverValueSetDestroyValue( ::sus::marker::UnsafeFnMarker) noexcept { static_assert(::sus::ops::Eq<decltype(ptr_), decltype(nullptr)>, "The `never_value` must be comparable to the named field."); ptr_ = nullptr; } static_assert(true); explicit constexpr StoragePointer(::sus::mem::NeverValueConstructor) noexcept : ptr_(nullptr) {} }; static_assert(std::is_trivially_copy_constructible_v<StoragePointer<int&>>); static_assert(std::is_trivially_copy_assignable_v<StoragePointer<int&>>); static_assert(std::is_trivially_move_constructible_v<StoragePointer<int&>>); static_assert(std::is_trivially_move_assignable_v<StoragePointer<int&>>); static_assert(::sus::mem::NeverValueField<StoragePointer<int&>>); } namespace sus::iter { template <class Item> class Once; template <class Item> constexpr Once<Item> once(::sus::option::Option<Item> o) noexcept; namespace __private { template <class T> requires requires(const T& t) { { t.iter() }; } constexpr auto begin(const T& t) noexcept; template <class T> requires requires(const T& t) { { t.iter() }; } constexpr auto end(const T& t) noexcept; } } namespace sus::option { using State::None; using State::Some; using ::sus::iter::Once; using ::sus::mem::__private::IsTrivialCopyAssignOrRef; using ::sus::mem::__private::IsTrivialCopyCtorOrRef; using ::sus::mem::__private::IsTrivialDtorOrRef; using ::sus::mem::__private::IsTrivialMoveAssignOrRef; using ::sus::mem::__private::IsTrivialMoveCtorOrRef; using ::sus::option::__private::Storage; using ::sus::option::__private::StoragePointer; namespace __private { template <class T, ::sus::iter::Iterator<Option<T>> Iter> requires ::sus::iter::Product<T> constexpr Option<T> from_product_impl(Iter&& it) noexcept; template <class T, ::sus::iter::Iterator<Option<T>> Iter> requires ::sus::iter::Sum<T> constexpr Option<T> from_sum_impl(Iter&& it) noexcept; } template <class T> class Option final { static_assert(!std::is_const_v<T>, "`Option<const T>` should be written `const Option<T>`, as " "const applies transitively."); static_assert( !std::is_rvalue_reference_v<T>, "`Option<T&&> is not supported, use Option<T&> or Option<const T&."); public: inline constexpr Option() noexcept = default; static inline constexpr Option with(const T& t) noexcept requires(!std::is_reference_v<T> && ::sus::mem::Copy<T>) { return Option(t); } static inline constexpr Option with(T&& t) noexcept requires(!std::is_reference_v<T>) { if constexpr (::sus::mem::Move<T>) { return Option(move_to_storage(t)); } else { static_assert(::sus::mem::Copy<T>, "All types should be Copy or Move."); return Option(t); } } template <std::convertible_to<T> U> __attribute__((pure)) static inline constexpr Option with(U&& t) noexcept requires(std::is_reference_v<T> && sus::construct::SafelyConstructibleFromReference<T, U &&>) { return Option(move_to_storage(t)); } static constexpr Option from(const T& val) noexcept requires(!std::is_reference_v<T> && ::sus::mem::Copy<T>) { return with(val); } static constexpr Option from(T&& val) noexcept requires(!std::is_reference_v<T>) { return with(::sus::move(val)); } template <std::convertible_to<T> U> __attribute__((pure)) static constexpr Option from(U&& val) noexcept requires(std::is_reference_v<T> && sus::construct::SafelyConstructibleFromReference<T, U &&>) { return with(::sus::forward<U>(val)); } template <::sus::iter::Iterator<Option<T>> Iter> requires ::sus::iter::Product<T> static constexpr Option from_product(Iter&& it) noexcept { return __private::from_product_impl<T>(::sus::move(it)); } template <::sus::iter::Iterator<Option<T>> Iter> requires ::sus::iter::Sum<T> static constexpr Option from_sum(Iter&& it) noexcept { return __private::from_sum_impl<T>(::sus::move(it)); } constexpr ~Option() noexcept requires(IsTrivialDtorOrRef<T>) = default; constexpr inline ~Option() noexcept requires(!IsTrivialDtorOrRef<T>) { if (t_.state() == Some) t_.destroy(); } constexpr Option(const Option& o) requires(::sus::mem::CopyOrRef<T> && IsTrivialCopyCtorOrRef<T>) = default; constexpr Option(const Option& o) noexcept requires(::sus::mem::CopyOrRef<T> && !IsTrivialCopyCtorOrRef<T>) { if (o.t_.state() == Some) t_.construct_from_none(copy_to_storage(o.t_.val())); } constexpr Option(const Option& o) requires(!::sus::mem::CopyOrRef<T>) = delete; constexpr Option(Option&& o) requires(::sus::mem::MoveOrRef<T> && IsTrivialMoveCtorOrRef<T>) = default; constexpr Option(Option&& o) noexcept requires(::sus::mem::MoveOrRef<T> && !IsTrivialMoveCtorOrRef<T>) { if (o.t_.state() == Some) t_.construct_from_none(o.t_.take_and_set_none()); } constexpr Option(Option&& o) requires(!::sus::mem::MoveOrRef<T>) = delete; constexpr Option& operator=(const Option& o) requires(::sus::mem::CopyOrRef<T> && IsTrivialCopyAssignOrRef<T>) = default; constexpr Option& operator=(const Option& o) noexcept requires(::sus::mem::CopyOrRef<T> && !IsTrivialCopyAssignOrRef<T>) { if (o.t_.state() == Some) t_.set_some(copy_to_storage(o.t_.val())); else if (t_.state() == Some) t_.set_none(); return *this; } constexpr Option& operator=(const Option& o) requires(!::sus::mem::CopyOrRef<T>) = delete; constexpr Option& operator=(Option&& o) requires(::sus::mem::MoveOrRef<T> && IsTrivialMoveAssignOrRef<T>) = default; constexpr Option& operator=(Option&& o) noexcept requires(::sus::mem::MoveOrRef<T> && !IsTrivialMoveAssignOrRef<T>) { if (o.t_.state() == Some) t_.set_some(o.t_.take_and_set_none()); else if (t_.state() == Some) t_.set_none(); return *this; } constexpr Option& operator=(Option&& o) requires(!::sus::mem::MoveOrRef<T>) = delete; constexpr Option clone() const& noexcept requires(::sus::mem::Clone<T> && !::sus::mem::CopyOrRef<T>) { if (t_.state() == Some) return Option(::sus::clone(t_.val())); else return Option(); } constexpr void clone_from(const Option& source) & noexcept requires(::sus::mem::Clone<T> && !::sus::mem::CopyOrRef<T>) { if (&source == this) [[unlikely]] return; if (t_.state() == Some && source.t_.state() == Some) { ::sus::clone_into(t_.val_mut(), source.t_.val()); } else { *this = source.clone(); } } __attribute__((pure)) constexpr bool is_some() const noexcept { return t_.state() == Some; } __attribute__((pure)) constexpr bool is_none() const noexcept { return t_.state() == None; } __attribute__((pure)) constexpr operator State() const& { return t_.state(); } constexpr __attribute__((nonnull)) T expect( const char* msg) && noexcept { ::sus::check_with_message(t_.state() == Some, *msg); return ::sus::move(*this).unwrap_unchecked(::sus::marker::unsafe_fn); } constexpr T unwrap() && noexcept { ::sus::check(t_.state() == Some); return ::sus::move(*this).unwrap_unchecked(::sus::marker::unsafe_fn); } constexpr T unwrap_or(T default_result) && noexcept { if (t_.state() == Some) { return t_.take_and_set_none(); } else { return default_result; } } constexpr T unwrap_or_else(::sus::fn::FnOnce<T()> auto&& f) && noexcept { if (t_.state() == Some) { return t_.take_and_set_none(); } else { return ::sus::fn::call_once(::sus::move(f)); } } constexpr T unwrap_or_default() && noexcept requires(!std::is_reference_v<T> && ::sus::construct::Default<T>) { if (t_.state() == Some) { return t_.take_and_set_none(); } else { return T(); } } constexpr inline T unwrap_unchecked( ::sus::marker::UnsafeFnMarker) && noexcept { return t_.take_and_set_none(); } __attribute__((pure)) constexpr const std::remove_reference_t<T>& as_value() const& noexcept { ::sus::check(t_.state() == Some); return t_.val(); } __attribute__((pure)) constexpr const std::remove_reference_t<T>& as_value() && noexcept requires(std::is_reference_v<T>) { ::sus::check(t_.state() == Some); return t_.val(); } __attribute__((pure)) constexpr std::remove_reference_t<T>& as_value_mut() & noexcept { ::sus::check(t_.state() == Some); return t_.val_mut(); } __attribute__((pure)) constexpr std::remove_reference_t<T>& as_value_mut() && noexcept requires(std::is_reference_v<T>) { ::sus::check(t_.state() == Some); return t_.val_mut(); } __attribute__((pure)) constexpr std::remove_reference_t<T>& as_value_mut() const& noexcept requires(std::is_reference_v<T>) { return ::sus::clone(*this).as_value_mut(); } __attribute__((pure)) constexpr const std::remove_reference_t<T>& as_value_unchecked( ::sus::marker::UnsafeFnMarker) const& noexcept { return t_.val(); } __attribute__((pure)) constexpr const std::remove_reference_t<T>& as_value_unchecked( ::sus::marker::UnsafeFnMarker) && noexcept requires(std::is_reference_v<T>) { return t_.val(); } __attribute__((pure)) constexpr std::remove_reference_t<T>& as_value_unchecked_mut( ::sus::marker::UnsafeFnMarker) & noexcept { return t_.val_mut(); } __attribute__((pure)) constexpr std::remove_reference_t<T>& as_value_unchecked_mut( ::sus::marker::UnsafeFnMarker) && noexcept requires(std::is_reference_v<T>) { return t_.val_mut(); } __attribute__((pure)) constexpr std::remove_reference_t<T>& as_value_unchecked_mut( ::sus::marker::UnsafeFnMarker) const& noexcept requires(std::is_reference_v<T>) { return ::sus::clone(*this).as_value_unchecked_mut(::sus::marker::unsafe_fn); } __attribute__((pure)) constexpr const std::remove_reference_t<T>& operator*() const& noexcept { ::sus::check(t_.state() == Some); return t_.val(); } __attribute__((pure)) constexpr const std::remove_reference_t<T>& operator*() && noexcept requires(std::is_reference_v<T>) { ::sus::check(t_.state() == Some); return t_.val(); } __attribute__((pure)) constexpr std::remove_reference_t<T>& operator*() & noexcept { ::sus::check(t_.state() == Some); return t_.val_mut(); } __attribute__((pure)) constexpr const std::remove_reference_t<T>* operator->() const& noexcept { ::sus::check(t_.state() == Some); return ::sus::mem::addressof( static_cast<const std::remove_reference_t<T>&>(t_.val())); } __attribute__((pure)) constexpr const std::remove_reference_t<T>* operator->() && noexcept requires(std::is_reference_v<T>) { ::sus::check(t_.state() == Some); return ::sus::mem::addressof( static_cast<const std::remove_reference_t<T>&>(t_.val())); } __attribute__((pure)) constexpr std::remove_reference_t<T>* operator->() & noexcept { ::sus::check(t_.state() == Some); return ::sus::mem::addressof( static_cast<std::remove_reference_t<T>&>(t_.val_mut())); } constexpr T& insert(T t) & noexcept requires(sus::mem::MoveOrRef<T>) { t_.set_some(move_to_storage(t)); return t_.val_mut(); } constexpr T& get_or_insert(T t) & noexcept requires(sus::mem::MoveOrRef<T>) { if (t_.state() == None) { t_.construct_from_none(move_to_storage(t)); } return t_.val_mut(); } constexpr T& get_or_insert_default() & noexcept requires(::sus::construct::Default<T>) { if (t_.state() == None) t_.construct_from_none(T()); return t_.val_mut(); } constexpr T& get_or_insert_with(::sus::fn::FnOnce<T()> auto&& f) & noexcept { if (t_.state() == None) { t_.construct_from_none( move_to_storage(::sus::fn::call_once(::sus::move(f)))); } return t_.val_mut(); } constexpr Option take() & noexcept { if (t_.state() == Some) return Option(t_.take_and_set_none()); else return Option(); } template <::sus::fn::FnOnce<::sus::fn::NonVoid(T&&)> MapFn, int&..., class R = std::invoke_result_t<MapFn&&, T&&>> constexpr Option<R> map(MapFn&& m) && noexcept { if (t_.state() == Some) { return Option<R>( ::sus::fn::call_once(::sus::move(m), t_.take_and_set_none())); } else { return Option<R>(); } } template <::sus::fn::FnOnce<::sus::fn::NonVoid(T&&)> MapFn, int&..., class R = std::invoke_result_t<MapFn&&, T&&>> constexpr Option<R> map(MapFn&& m) const& noexcept requires(::sus::mem::CopyOrRef<T>) { return ::sus::clone(*this).map(::sus::move(m)); } template <::sus::fn::FnOnce<::sus::fn::NonVoid(T&&)> MapFn, int&..., class R = std::invoke_result_t<MapFn&&, T&&>> constexpr R map_or(R default_result, MapFn&& m) && noexcept { if (t_.state() == Some) { return ::sus::fn::call_once(::sus::move(m), t_.take_and_set_none()); } else { return default_result; } } template <::sus::fn::FnOnce<::sus::fn::NonVoid(T&&)> MapFn, int&..., class R = std::invoke_result_t<MapFn&&, T&&>> constexpr R map_or(R default_result, MapFn&& m) const& noexcept requires(::sus::mem::CopyOrRef<T>) { return ::sus::clone(*this).map_or(::sus::move(default_result), ::sus::move(m)); } template <::sus::fn::FnOnce<::sus::fn::NonVoid()> DefaultFn, ::sus::fn::FnOnce<::sus::fn::NonVoid(T&&)> MapFn, int&..., class D = std::invoke_result_t<DefaultFn>, class R = std::invoke_result_t<MapFn, T&&>> requires(std::is_same_v<D, R>) constexpr R map_or_else(DefaultFn&& default_fn, MapFn&& m) && noexcept { if (t_.state() == Some) { return ::sus::fn::call_once(::sus::move(m), t_.take_and_set_none()); } else { return ::sus::move(default_fn)(); } } template <::sus::fn::FnOnce<::sus::fn::NonVoid()> DefaultFn, ::sus::fn::FnOnce<::sus::fn::NonVoid(T&&)> MapFn, int&..., class D = std::invoke_result_t<DefaultFn>, class R = std::invoke_result_t<MapFn, T&&>> requires(std::is_same_v<D, R>) constexpr R map_or_else(DefaultFn&& default_fn, MapFn&& m) const& noexcept requires(::sus::mem::CopyOrRef<T>) { return ::sus::clone(*this).map_or_else(::sus::move(default_fn), ::sus::move(m)); } constexpr Option<T> filter( ::sus::fn::FnOnce<bool(const T&)> auto&& p) && noexcept { if (t_.state() == Some) { if (::sus::fn::call_once(::sus::move(p), t_.val())) { return Option(t_.take_and_set_none()); } else { t_.set_none(); return Option(); } } else { return Option(); } } constexpr Option<T> filter( ::sus::fn::FnOnce<bool(const T&)> auto&& p) const& noexcept requires(::sus::mem::CopyOrRef<T>) { return ::sus::clone(*this).filter(::sus::move(p)); } template <class U> constexpr Option<U> and_that(Option<U> opt) && noexcept { if (t_.state() == Some) { t_.set_none(); } else { opt = Option<U>(); } return opt; } template <class U> constexpr Option<U> and_that(Option<U> opt) const& noexcept requires(::sus::mem::CopyOrRef<T>) { return ::sus::clone(*this).and_that(::sus::move(opt)); } template <::sus::fn::FnOnce<::sus::fn::NonVoid(T&&)> AndFn, int&..., class R = std::invoke_result_t<AndFn, T&&>, class U = ::sus::option::__private::IsOptionType<R>::inner_type> requires(::sus::option::__private::IsOptionType<R>::value) constexpr Option<U> and_then(AndFn&& f) && noexcept { if (t_.state() == Some) return ::sus::fn::call_once(::sus::move(f), t_.take_and_set_none()); else return Option<U>(); } template <::sus::fn::FnOnce<::sus::fn::NonVoid(T&&)> AndFn, int&..., class R = std::invoke_result_t<AndFn, T&&>, class U = ::sus::option::__private::IsOptionType<R>::inner_type> requires(::sus::option::__private::IsOptionType<R>::value) constexpr Option<U> and_then(AndFn&& f) const& noexcept requires(::sus::mem::CopyOrRef<T>) { return ::sus::clone(*this).and_then(::sus::move(f)); } constexpr Option<T> or_that(Option<T> opt) && noexcept { if (t_.state() == Some) return Option(t_.take_and_set_none()); else return opt; } constexpr Option<T> or_that(Option<T> opt) const& noexcept requires(::sus::mem::CopyOrRef<T>) { return ::sus::clone(*this).or_that(::sus::move(opt)); } constexpr Option<T> or_else( ::sus::fn::FnOnce<Option<T>()> auto&& f) && noexcept { if (t_.state() == Some) return Option(t_.take_and_set_none()); else return ::sus::fn::call_once(::sus::move(f)); } constexpr Option<T> or_else( ::sus::fn::FnOnce<Option<T>()> auto&& f) const& noexcept requires(::sus::mem::CopyOrRef<T>) { return ::sus::clone(*this).or_else(::sus::move(f)); } constexpr Option<T> xor_that(Option<T> opt) && noexcept { if (t_.state() == Some) { if (opt.t_.state() == None) { return Option(t_.take_and_set_none()); } else { t_.set_none(); return Option(); } } else { return opt; } } constexpr Option<T> xor_that(Option<T> opt) const& noexcept requires(::sus::mem::CopyOrRef<T>) { return ::sus::clone(*this).xor_that(::sus::move(opt)); } template <class E, int&..., class Result = ::sus::result::Result<T, E>> constexpr Result ok_or(E e) && noexcept requires(!std::is_reference_v<T> && !std::is_reference_v<E>) { if (t_.state() == Some) return Result::with(t_.take_and_set_none()); else return Result::with_err(::sus::move(e)); } template <class E, int&..., class Result = ::sus::result::Result<T, E>> constexpr Result ok_or(E e) const& noexcept requires(!std::is_reference_v<T> && !std::is_reference_v<E> && ::sus::mem::CopyOrRef<T>) { return ::sus::clone(*this).ok_or(::sus::move(e)); } template <::sus::fn::FnOnce<::sus::fn::NonVoid()> ElseFn, int&..., class E = std::invoke_result_t<ElseFn>, class Result = ::sus::result::Result<T, E>> constexpr Result ok_or_else(ElseFn&& f) && noexcept requires(!std::is_reference_v<T> && !std::is_reference_v<E>) { if (t_.state() == Some) return Result::with(t_.take_and_set_none()); else return Result::with_err(::sus::fn::call_once(::sus::move(f))); } template <::sus::fn::FnOnce<::sus::fn::NonVoid()> ElseFn, int&..., class E = std::invoke_result_t<ElseFn>, class Result = ::sus::result::Result<T, E>> constexpr Result ok_or_else(ElseFn&& f) const& noexcept requires(!std::is_reference_v<T> && !std::is_reference_v<E> && ::sus::mem::CopyOrRef<T>) { return ::sus::clone(*this).ok_or_else(::sus::move(f)); } template <int&..., class OkType = typename ::sus::result::__private::IsResultType<T>::ok_type, class ErrType = typename ::sus::result::__private::IsResultType<T>::err_type, class Result = ::sus::result::Result<Option<OkType>, ErrType>> requires(::sus::result::__private::IsResultType<T>::value) constexpr Result transpose() && noexcept { if (t_.state() == None) { return Result::with(Option<OkType>()); } else { if (t_.val().is_ok()) { return Result::with(Option<OkType>::with( t_.take_and_set_none().unwrap_unchecked(::sus::marker::unsafe_fn))); } else { return Result::with_err(t_.take_and_set_none().unwrap_err_unchecked( ::sus::marker::unsafe_fn)); } } } template <int&..., class OkType = typename ::sus::result::__private::IsResultType<T>::ok_type, class ErrType = typename ::sus::result::__private::IsResultType<T>::err_type, class Result = ::sus::result::Result<Option<OkType>, ErrType>> requires(::sus::result::__private::IsResultType<T>::value) constexpr Result transpose() const& noexcept requires(::sus::mem::CopyOrRef<T>) { return ::sus::clone(*this).transpose(); } template <class U, int&..., class Tuple = ::sus::tuple_type::Tuple<T, U>> constexpr Option<Tuple> zip(Option<U> o) && noexcept { if (o.t_.state() == None) { if (t_.state() == Some) t_.set_none(); return Option<Tuple>(); } else if (t_.state() == None) { return Option<Tuple>(); } else { return Option<Tuple>::with(Tuple::with( ::sus::move(*this).unwrap_unchecked(::sus::marker::unsafe_fn), ::sus::move(o).unwrap_unchecked(::sus::marker::unsafe_fn))); } } template <class U, int&..., class Tuple = ::sus::tuple_type::Tuple<T, U>> constexpr Option<Tuple> zip(Option<U> o) const& noexcept requires(::sus::mem::CopyOrRef<T>) { return ::sus::clone(*this).zip(::sus::move(o)); } constexpr auto unzip() && noexcept requires(!std::is_reference_v<T> && __private::IsTupleOfSizeTwo<T>::value) { using U = __private::IsTupleOfSizeTwo<T>::first_type; using V = __private::IsTupleOfSizeTwo<T>::second_type; if (is_some()) { auto&& [u, v] = t_.take_and_set_none(); return ::sus::tuple_type::Tuple<Option<U>, Option<V>>::with( Option<U>::with(::sus::forward<U>(u)), Option<V>::with(::sus::forward<V>(v))); } else { return ::sus::tuple_type::Tuple<Option<U>, Option<V>>::with(Option<U>(), Option<V>()); } } constexpr auto unzip() const& noexcept requires(!std::is_reference_v<T> && __private::IsTupleOfSizeTwo<T>::value && ::sus::mem::CopyOrRef<T>) { return ::sus::clone(*this).unzip(); } constexpr Option replace(T t) & noexcept requires(sus::mem::MoveOrRef<T>) { if (t_.state() == None) { t_.construct_from_none(move_to_storage(t)); return Option(); } else { return Option(t_.replace_some(move_to_storage(t))); } } constexpr Option<std::remove_const_t<std::remove_reference_t<T>>> copied() const& noexcept requires(std::is_reference_v<T> && ::sus::mem::Copy<T>) { if (t_.state() == None) { return Option<std::remove_const_t<std::remove_reference_t<T>>>(); } else { return Option<std::remove_const_t<std::remove_reference_t<T>>>::with( t_.val()); } } constexpr Option<std::remove_const_t<std::remove_reference_t<T>>> cloned() const& noexcept requires(std::is_reference_v<T> && ::sus::mem::Clone<T>) { if (t_.state() == None) { return Option<std::remove_const_t<std::remove_reference_t<T>>>(); } else { return Option<std::remove_const_t<std::remove_reference_t<T>>>::with( ::sus::clone<std::remove_reference_t<T>>(t_.val())); } } constexpr T flatten() && noexcept requires(::sus::option::__private::IsOptionType<T>::value) { if (t_.state() == Some) return ::sus::move(*this).unwrap_unchecked(::sus::marker::unsafe_fn); else return T(); } constexpr T flatten() const& noexcept requires(::sus::option::__private::IsOptionType<T>::value && ::sus::mem::CopyOrRef<T>) { return ::sus::clone(*this).flatten(); } __attribute__((pure)) constexpr Option<const std::remove_reference_t<T>&> as_ref() const& noexcept { if (t_.state() == None) return Option<const std::remove_reference_t<T>&>(); else return Option<const std::remove_reference_t<T>&>(t_.val()); } __attribute__((pure)) constexpr Option<const std::remove_reference_t<T>&> as_ref() && noexcept requires(std::is_reference_v<T>) { if (t_.state() == None) return Option<const std::remove_reference_t<T>&>(); else return Option<const std::remove_reference_t<T>&>(t_.take_and_set_none()); } __attribute__((pure)) constexpr Option<T&> as_mut() & noexcept { if (t_.state() == None) return Option<T&>(); else return Option<T&>(t_.val_mut()); } __attribute__((pure)) constexpr Option<T&> as_mut() && noexcept requires(std::is_reference_v<T>) { if (t_.state() == None) return Option<T&>(); else return Option<T&>(t_.take_and_set_none()); } __attribute__((pure)) constexpr Option<T&> as_mut() const& noexcept requires(std::is_reference_v<T>) { return ::sus::clone(*this).as_mut(); } __attribute__((pure)) constexpr Once<const std::remove_reference_t<T>&> iter() const& noexcept { return ::sus::iter::once<const std::remove_reference_t<T>&>(as_ref()); } constexpr Once<const std::remove_reference_t<T>&> iter() && noexcept requires(std::is_reference_v<T>) { return ::sus::iter::once<const std::remove_reference_t<T>&>( ::sus::move(*this).as_ref()); } constexpr Once<const std::remove_reference_t<T>&> iter() const& noexcept requires(std::is_reference_v<T>) { return ::sus::clone(*this).iter(); } __attribute__((pure)) constexpr Once<T&> iter_mut() & noexcept { return ::sus::iter::once<T&>(as_mut()); } constexpr Once<T&> iter_mut() && noexcept requires(std::is_reference_v<T>) { return ::sus::iter::once<T&>(::sus::move(*this).as_mut()); } constexpr Once<T&> iter_mut() const& noexcept requires(std::is_reference_v<T>) { return ::sus::clone(*this).iter_mut(); } constexpr Once<T> into_iter() && noexcept { return ::sus::iter::once<T>(take()); } constexpr Once<T> into_iter() const& noexcept requires(::sus::mem::CopyOrRef<T>) { return ::sus::clone(*this).into_iter(); } friend constexpr inline bool operator==(const Option& l, const Option& r) noexcept requires(::sus::ops::Eq<T>) { switch (l) { case Some: return r.is_some() && (l.as_value_unchecked(::sus::marker::unsafe_fn) == r.as_value_unchecked(::sus::marker::unsafe_fn)); case None: return r.is_none(); } ::sus::unreachable_unchecked(::sus::marker::unsafe_fn); } template <class U> requires(::sus::ops::Eq<T, U>) friend constexpr inline bool operator==(const Option<T>& l, const Option<U>& r) noexcept { switch (l) { case Some: return r.is_some() && (l.as_value_unchecked(::sus::marker::unsafe_fn) == r.as_value_unchecked(::sus::marker::unsafe_fn)); case None: return r.is_none(); } ::sus::unreachable_unchecked(::sus::marker::unsafe_fn); } template <class U> requires(!::sus::ops::Eq<T, U>) friend constexpr inline bool operator==(const Option<T>& l, const Option<U>& r) = delete; friend constexpr inline auto operator<=>(const Option& l, const Option& r) noexcept requires(::sus::ops::ExclusiveOrd<T>) { switch (l) { case Some: if (r.is_some()) { return l.as_value_unchecked(::sus::marker::unsafe_fn) <=> r.as_value_unchecked(::sus::marker::unsafe_fn); } else { return std::strong_ordering::greater; } case None: if (r.is_some()) return std::strong_ordering::less; else return std::strong_ordering::equivalent; } ::sus::unreachable_unchecked(::sus::marker::unsafe_fn); } template <class U> requires(::sus::ops::ExclusiveOrd<T, U>) friend constexpr inline auto operator<=>(const Option<T>& l, const Option<U>& r) noexcept { switch (l) { case Some: if (r.is_some()) { return l.as_value_unchecked(::sus::marker::unsafe_fn) <=> r.as_value_unchecked(::sus::marker::unsafe_fn); } else { return std::strong_ordering::greater; } case None: if (r.is_some()) return std::strong_ordering::less; else return std::strong_ordering::equivalent; } ::sus::unreachable_unchecked(::sus::marker::unsafe_fn); } friend constexpr inline auto operator<=>(const Option& l, const Option& r) noexcept requires(::sus::ops::ExclusiveWeakOrd<T>) { switch (l) { case Some: if (r.is_some()) { return l.as_value_unchecked(::sus::marker::unsafe_fn) <=> r.as_value_unchecked(::sus::marker::unsafe_fn); } else { return std::weak_ordering::greater; } case None: if (r.is_some()) return std::weak_ordering::less; else return std::weak_ordering::equivalent; } ::sus::unreachable_unchecked(::sus::marker::unsafe_fn); } template <class U> requires(::sus::ops::ExclusiveWeakOrd<T, U>) friend constexpr inline auto operator<=>(const Option<T>& l, const Option<U>& r) noexcept { switch (l) { case Some: if (r.is_some()) { return l.as_value_unchecked(::sus::marker::unsafe_fn) <=> r.as_value_unchecked(::sus::marker::unsafe_fn); } else { return std::weak_ordering::greater; } case None: if (r.is_some()) return std::weak_ordering::less; else return std::weak_ordering::equivalent; } ::sus::unreachable_unchecked(::sus::marker::unsafe_fn); } template <class U> requires(::sus::ops::ExclusivePartialOrd<T, U>) friend constexpr inline auto operator<=>(const Option<T>& l, const Option<U>& r) noexcept { switch (l) { case Some: if (r.is_some()) { return l.as_value_unchecked(::sus::marker::unsafe_fn) <=> r.as_value_unchecked(::sus::marker::unsafe_fn); } else { return std::partial_ordering::greater; } case None: if (r.is_some()) return std::partial_ordering::less; else return std::partial_ordering::equivalent; } ::sus::unreachable_unchecked(::sus::marker::unsafe_fn); } friend constexpr inline auto operator<=>(const Option& l, const Option& r) noexcept requires(::sus::ops::ExclusivePartialOrd<T>) { switch (l) { case Some: if (r.is_some()) { return l.as_value_unchecked(::sus::marker::unsafe_fn) <=> r.as_value_unchecked(::sus::marker::unsafe_fn); } else { return std::partial_ordering::greater; } case None: if (r.is_some()) return std::partial_ordering::less; else return std::partial_ordering::equivalent; } ::sus::unreachable_unchecked(::sus::marker::unsafe_fn); } template <class U> requires(!::sus::ops::PartialOrd<T, U>) friend constexpr inline auto operator<=>( const Option<T>& l, const Option<U>& r) noexcept = delete; constexpr static Option from( const std::optional<std::remove_reference_t<T>>& s) noexcept requires(::sus::mem::Copy<T> && !std::is_reference_v<T>); constexpr static Option from( std::optional<std::remove_reference_t<T>>&& s) noexcept requires(::sus::mem::Move<T> && !std::is_reference_v<T>); template <::sus::construct::Into<T> U> static inline constexpr Option from(const std::optional<U>& s) noexcept requires(!std::is_reference_v<T>); template <::sus::construct::Into<T> U> static inline constexpr Option from(std::optional<U>&& s) noexcept requires(!std::is_reference_v<T>); constexpr Option(const std::optional<std::remove_reference_t<T>>& s) noexcept requires(::sus::mem::Copy<T> && !std::is_reference_v<T>); constexpr Option(std::optional<std::remove_reference_t<T>>&& s) noexcept requires(::sus::mem::Move<T> && !std::is_reference_v<T>); constexpr operator std::optional<std::remove_reference_t<T>>() const& noexcept requires(::sus::mem::Copy<T> && !std::is_reference_v<T>); constexpr operator std::optional<std::remove_reference_t<T>>() && noexcept requires(::sus::mem::Move<T> && !std::is_reference_v<T>); constexpr operator std::optional<const std::remove_reference_t<T>*>() const& noexcept requires(std::is_reference_v<T>); constexpr operator std::optional<std::remove_reference_t<T>*>() const& noexcept requires(!std::is_const_v<std::remove_reference_t<T>> && std::is_reference_v<T>); private: template <class U> friend class Option; template <class U> static constexpr inline decltype(auto) copy_to_storage(const U& t) { if constexpr (std::is_reference_v<T>) return StoragePointer<T>(t); else return t; } template <class U> static constexpr inline decltype(auto) move_to_storage(U&& t) { if constexpr (std::is_reference_v<T>) return StoragePointer<T>(t); else return ::sus::move(t); } constexpr explicit Option(T t) requires(std::is_reference_v<T>) : t_(StoragePointer<T>(t)) {} constexpr explicit Option(const T& t) requires(!std::is_reference_v<T>) : t_(t) {} constexpr explicit Option(T&& t) requires(!std::is_reference_v<T> && ::sus::mem::MoveOrRef<T>) : t_(::sus::move(t)) {} template <class U> using StorageType = std::conditional_t<std::is_reference_v<U>, Storage<StoragePointer<U>>, Storage<U>>; StorageType<T> t_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<StorageType<T> >; }; using ::sus::iter::__private::begin; using ::sus::iter::__private::end; template <class T> [[nodiscard]] inline constexpr __private::SomeMarker<T&&> some( T&& t) noexcept { return __private::SomeMarker<T&&>(::sus::forward<T>(t)); } __attribute__((const)) inline constexpr auto none() noexcept { return __private::NoneMarker(); } } template <class T> struct sus::ops::TryImpl<::sus::option::Option<T>> { using Output = T; constexpr static bool is_success(const ::sus::option::Option<T>& t) { return t.is_some(); } constexpr static Output into_output(::sus::option::Option<T> t) { return ::sus::move(t).unwrap_unchecked(::sus::marker::unsafe_fn); } constexpr static ::sus::option::Option<T> from_output(Output t) { return ::sus::option::Option<T>::with(::sus::move(t)); } }; template <class T> struct std::hash<::sus::option::Option<T>> { auto operator()(const ::sus::option::Option<T>& u) const noexcept { if (u.is_some()) return std::hash<T>()(*u); else return 0; } }; template <class T> requires(::sus::ops::Eq<T>) struct std::equal_to<::sus::option::Option<T>> { constexpr auto operator()(const ::sus::option::Option<T>& l, const ::sus::option::Option<T>& r) const noexcept { return l == r; } }; namespace sus { using ::sus::option::none; using ::sus::option::None; using ::sus::option::Option; using ::sus::option::some; using ::sus::option::Some; } namespace sus::assertions { constexpr inline __attribute__((always_inline)) bool is_big_endian() { return false; } constexpr inline __attribute__((always_inline)) bool is_little_endian() noexcept { return !is_big_endian(); } } namespace sus::num::__private::int_log10 { __attribute__((const)) inline __attribute__((always_inline)) constexpr uint32_t less_than_5( uint32_t val) noexcept { constexpr uint32_t C1 = 0b011'00000000000000000 - 10; constexpr uint32_t C2 = 0b100'00000000000000000 - 100; constexpr uint32_t C3 = 0b111'00000000000000000 - 1000; constexpr uint32_t C4 = 0b100'00000000000000000 - 10000; return (((val + C1) & (val + C2)) ^ ((val + C3) & (val + C4))) >> 17; } __attribute__((const)) inline __attribute__((always_inline)) constexpr uint32_t u8(uint8_t val) { return less_than_5(uint32_t{val}); } __attribute__((const)) inline __attribute__((always_inline)) constexpr uint32_t u16(uint16_t val) noexcept { return less_than_5(uint32_t{val}); } __attribute__((const)) inline __attribute__((always_inline)) constexpr uint32_t u32(uint32_t val) noexcept { auto log = uint32_t{0}; if (val >= 100'000) { val /= 100'000; log += 5; } return log + less_than_5(val); } __attribute__((const)) inline __attribute__((always_inline)) constexpr uint32_t u64(uint64_t val) noexcept { auto log = uint32_t{0}; if (val >= 10'000'000'000) { val /= 10'000'000'000; log += 10; } if (val >= 100'000) { val /= 100'000; log += 5; } return log + less_than_5(static_cast<uint32_t>(val)); } __attribute__((const)) inline __attribute__((always_inline)) constexpr uint32_t usize( uint32_t val) noexcept { return u32(val); } __attribute__((const)) inline __attribute__((always_inline)) constexpr uint32_t usize( uint64_t val) noexcept { return u64(val); } __attribute__((const)) inline __attribute__((always_inline)) constexpr uint32_t uptr( uint32_t val) noexcept { return u32(val); } __attribute__((const)) inline __attribute__((always_inline)) constexpr uint32_t uptr( uint64_t val) noexcept { return u64(val); } __attribute__((const)) inline __attribute__((always_inline)) constexpr uint32_t i8(int8_t val) { return u8(static_cast<uint8_t>(val)); } __attribute__((const)) inline __attribute__((always_inline)) constexpr uint32_t i16(int16_t val) noexcept { return u16(static_cast<uint16_t>(val)); } __attribute__((const)) inline __attribute__((always_inline)) constexpr uint32_t i32(int32_t val) noexcept { return u32(static_cast<uint32_t>(val)); } __attribute__((const)) inline __attribute__((always_inline)) constexpr uint32_t i64(int64_t val) noexcept { return u64(static_cast<uint64_t>(val)); } __attribute__((const)) inline __attribute__((always_inline)) constexpr uint32_t isize( int32_t val) noexcept { return usize(static_cast<uint32_t>(val)); } constexpr inline __attribute__((always_inline)) uint32_t isize(int64_t val) noexcept { return usize(static_cast<uint64_t>(val)); } } namespace sus::num { enum class FpCategory { Nan, Infinite, Zero, Subnormal, Normal }; } namespace sus::num::__private { template <class T> struct OverflowOut final { bool overflow; T value; }; template <class T> requires(std::is_integral_v<T>) using MathType = std::conditional_t< ::sus::mem::size_of<T>() >= ::sus::mem::size_of<int>(), T, std::conditional_t<std::is_signed_v<T>, int, unsigned int>>; template <class T> __attribute__((const)) inline __attribute__((always_inline)) constexpr uint32_t unchecked_sizeof() noexcept { static_assert(::sus::mem::size_of<T>() <= 0xfffffff); return static_cast<uint32_t>(::sus::mem::size_of<T>()); } template <class T> requires(std::is_integral_v<T> && std::is_signed_v<T>) __attribute__((const)) inline __attribute__((always_inline)) constexpr T unchecked_neg(T x) noexcept { return static_cast<T>(-MathType<T>{x}); } template <class T> requires(std::is_integral_v<T> && !std::is_signed_v<T>) __attribute__((const)) inline __attribute__((always_inline)) constexpr T unchecked_not(T x) noexcept { return static_cast<T>(~MathType<T>{x}); } template <class T> requires(std::is_integral_v<T>) __attribute__((const)) inline __attribute__((always_inline)) constexpr T unchecked_add(T x, T y) noexcept { return static_cast<T>(MathType<T>{x} + MathType<T>{y}); } template <class T> requires(std::is_integral_v<T>) __attribute__((const)) inline __attribute__((always_inline)) constexpr T unchecked_sub(T x, T y) noexcept { return static_cast<T>(MathType<T>{x} - MathType<T>{y}); } template <class T> requires(std::is_integral_v<T>) __attribute__((const)) inline __attribute__((always_inline)) constexpr T unchecked_mul(T x, T y) noexcept { return static_cast<T>(MathType<T>{x} * MathType<T>{y}); } template <class T> requires(std::is_integral_v<T>) __attribute__((const)) inline __attribute__((always_inline)) constexpr T unchecked_div(T x, T y) noexcept { return static_cast<T>(MathType<T>{x} / MathType<T>{y}); } template <class T> requires(std::is_integral_v<T>) __attribute__((const)) inline __attribute__((always_inline)) constexpr T unchecked_rem(T x, T y) noexcept { return static_cast<T>(MathType<T>{x} % MathType<T>{y}); } template <class T> requires(std::is_integral_v<T>) __attribute__((const)) inline __attribute__((always_inline)) constexpr T unchecked_and(T x, T y) noexcept { return static_cast<T>(MathType<T>{x} & MathType<T>{y}); } template <class T> requires(std::is_integral_v<T>) __attribute__((const)) inline __attribute__((always_inline)) constexpr T unchecked_or(T x, T y) noexcept { return static_cast<T>(MathType<T>{x} | MathType<T>{y}); } template <class T> requires(std::is_integral_v<T>) __attribute__((const)) inline __attribute__((always_inline)) constexpr T unchecked_xor(T x, T y) noexcept { return static_cast<T>(MathType<T>{x} ^ MathType<T>{y}); } template <class T> requires(std::is_integral_v<T> && !std::is_signed_v<T>) __attribute__((const)) inline __attribute__((always_inline)) constexpr T unchecked_shl( T x, uint32_t y) noexcept { return static_cast<T>(MathType<T>{x} << y); } template <class T> requires(std::is_integral_v<T> && !std::is_signed_v<T>) __attribute__((const)) inline __attribute__((always_inline)) constexpr T unchecked_shr( T x, uint32_t y) noexcept { return static_cast<T>(MathType<T>{x} >> y); } template <class T> requires(std::is_integral_v<T>) __attribute__((const)) inline __attribute__((always_inline)) constexpr uint32_t num_bits() noexcept { return unchecked_mul(unchecked_sizeof<T>(), uint32_t{8}); } template <class T> requires(std::is_integral_v<T> && ::sus::mem::size_of<T>() <= 8) __attribute__((const)) inline __attribute__((always_inline)) constexpr T high_bit() noexcept { if constexpr (::sus::mem::size_of<T>() == 1) return static_cast<T>(0x80); else if constexpr (::sus::mem::size_of<T>() == 2) return static_cast<T>(0x8000); else if constexpr (::sus::mem::size_of<T>() == 4) return static_cast<T>(0x80000000); else return static_cast<T>(0x8000000000000000); } template <class T> requires(std::is_floating_point_v<T> && ::sus::mem::size_of<T>() == 4) __attribute__((const)) inline __attribute__((always_inline)) constexpr uint32_t high_bit() noexcept { return uint32_t{0x80000000}; } template <class T> requires(std::is_floating_point_v<T> && ::sus::mem::size_of<T>() == 8) __attribute__((const)) inline __attribute__((always_inline)) constexpr uint64_t high_bit() noexcept { return uint64_t{0x8000000000000000}; } template <class T> requires(std::is_integral_v<T> && !std::is_signed_v<T>) __attribute__((const)) inline __attribute__((always_inline)) constexpr T max_value() noexcept { return unchecked_not(T{0}); } template <class T> requires(std::is_integral_v<T> && std::is_signed_v<T> && ::sus::mem::size_of<T>() <= 8) __attribute__((const)) inline __attribute__((always_inline)) constexpr T max_value() noexcept { if constexpr (::sus::mem::size_of<T>() == 1) return T{0x7f}; else if constexpr (::sus::mem::size_of<T>() == 2) return T{0x7fff}; else if constexpr (::sus::mem::size_of<T>() == 4) return T{0x7fffffff}; else return T{0x7fffffffffffffff}; } template <class T> requires(std::is_integral_v<T> && !std::is_signed_v<T>) __attribute__((const)) inline __attribute__((always_inline)) constexpr T min_value() noexcept { return T{0}; } template <class T> requires(std::is_integral_v<T> && std::is_signed_v<T> && ::sus::mem::size_of<T>() <= 8) __attribute__((const)) inline __attribute__((always_inline)) constexpr T min_value() noexcept { return -max_value<T>() - T{1}; } template <class T> requires(std::is_floating_point_v<T>) __attribute__((const)) inline __attribute__((always_inline)) constexpr T epsilon() noexcept { if constexpr (::sus::mem::size_of<T>() == ::sus::mem::size_of<float>()) return 1.1920929E-7f; else return 2.2204460492503131E-16; } template <class T> requires(std::is_floating_point_v<T>) __attribute__((const)) inline __attribute__((always_inline)) constexpr T max_value() noexcept { if constexpr (::sus::mem::size_of<T>() == ::sus::mem::size_of<float>()) { return 340282346638528859811704183484516925440.f; } else return 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.0; } template <class T> requires(std::is_floating_point_v<T>) __attribute__((const)) inline __attribute__((always_inline)) constexpr T min_value() noexcept { if constexpr (::sus::mem::size_of<T>() == ::sus::mem::size_of<float>()) return -340282346638528859811704183484516925440.f; else return -179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.0; } template <class T> requires(std::is_integral_v<T> && std::is_unsigned_v<T> && ::sus::mem::size_of<T>() <= 8) __attribute__((const)) inline __attribute__((always_inline)) constexpr uint32_t count_ones( T value) noexcept { if constexpr (::sus::mem::size_of<T>() <= ::sus::mem::size_of<unsigned int>()) { using U = unsigned int; return static_cast<uint32_t>(__builtin_popcount(U{value})); } else if constexpr (::sus::mem::size_of<T>() <= ::sus::mem::size_of<unsigned long>()) { using U = unsigned long; return static_cast<uint32_t>(__builtin_popcountl(U{value})); } else { using U = unsigned long long; return static_cast<uint32_t>(__builtin_popcountll(U{value})); } } template <class T> requires(std::is_integral_v<T> && std::is_unsigned_v<T> && ::sus::mem::size_of<T>() <= 8) __attribute__((const)) inline __attribute__((always_inline)) constexpr uint32_t leading_zeros_nonzero( ::sus::marker::UnsafeFnMarker, T value) noexcept { if (std::is_constant_evaluated()) { uint32_t count = 0; for (auto i = uint32_t{0}; i < unchecked_mul(unchecked_sizeof<T>(), uint32_t{8}); ++i) { const bool zero = (value & high_bit<T>()) == 0; if (!zero) break; count += 1; value <<= 1; } return count; } if constexpr (::sus::mem::size_of<T>() <= ::sus::mem::size_of<unsigned int>()) { using U = unsigned int; return static_cast<uint32_t>( __builtin_clz(U{value}) - ((::sus::mem::size_of<unsigned int>() - ::sus::mem::size_of<T>()) * 8u)); } else if constexpr (::sus::mem::size_of<T>() <= ::sus::mem::size_of<unsigned long>()) { using U = unsigned long; return static_cast<uint32_t>(__builtin_clzl(U{value})); } else { using U = unsigned long long; return static_cast<uint32_t>(__builtin_clzll(U{value})); } } template <class T> requires(std::is_integral_v<T> && std::is_unsigned_v<T> && ::sus::mem::size_of<T>() <= 8) __attribute__((const)) inline __attribute__((always_inline)) constexpr uint32_t leading_zeros( T value) noexcept { if (value == 0) return unchecked_mul(unchecked_sizeof<T>(), uint32_t{8}); return leading_zeros_nonzero(::sus::marker::unsafe_fn, value); } template <class T> requires(std::is_integral_v<T> && std::is_unsigned_v<T> && ::sus::mem::size_of<T>() <= 8) __attribute__((const)) inline __attribute__((always_inline)) constexpr uint32_t trailing_zeros_nonzero( ::sus::marker::UnsafeFnMarker, T value) noexcept { if (std::is_constant_evaluated()) { uint32_t count = 0; for (auto i = uint32_t{0}; i < unchecked_mul(unchecked_sizeof<T>(), uint32_t{8}); ++i) { const bool zero = (value & 1) == 0; if (!zero) break; count += 1; value >>= 1; } return count; } if constexpr (::sus::mem::size_of<T>() <= ::sus::mem::size_of<unsigned int>()) { using U = unsigned int; return static_cast<uint32_t>(__builtin_ctz(U{value})); } else if constexpr (::sus::mem::size_of<T>() <= ::sus::mem::size_of<unsigned long>()) { using U = unsigned long; return static_cast<uint32_t>(__builtin_ctzl(U{value})); } else { using U = unsigned long long; return static_cast<uint32_t>(__builtin_ctzll(U{value})); } } template <class T> requires(std::is_integral_v<T> && std::is_unsigned_v<T> && ::sus::mem::size_of<T>() <= 8) __attribute__((const)) inline __attribute__((always_inline)) constexpr uint32_t trailing_zeros( T value) noexcept { if (value == 0) return static_cast<uint32_t>(::sus::mem::size_of<T>() * 8u); return trailing_zeros_nonzero(::sus::marker::unsafe_fn, value); } template <class T> requires(std::is_integral_v<T> && std::is_unsigned_v<T> && ::sus::mem::size_of<T>() <= 8) __attribute__((const)) inline __attribute__((always_inline)) constexpr T reverse_bits(T value) noexcept { uint32_t bits = unchecked_mul(unchecked_sizeof<T>(), uint32_t{8}); auto mask = unchecked_not(T(0)); while ((bits >>= 1) > 0) { mask ^= unchecked_shl(mask, bits); value = (unchecked_shr(value, bits) & mask) | (unchecked_shl(value, bits) & ~mask); } return value; } template <class T> requires(std::is_integral_v<T> && std::is_unsigned_v<T>) __attribute__((const)) inline constexpr T rotate_left(T value, uint32_t n) noexcept { const uint32_t num_bits = unchecked_mul(unchecked_sizeof<T>(), uint32_t{8}); if (n >= num_bits) n %= num_bits; if (n == 0) return value; const auto rshift = unchecked_sub(num_bits, n); return unchecked_shl(value, n) | unchecked_shr(value, rshift); } template <class T> requires(std::is_integral_v<T> && std::is_unsigned_v<T>) __attribute__((const)) inline constexpr T rotate_right(T value, uint32_t n) noexcept { const uint32_t num_bits = unchecked_mul(unchecked_sizeof<T>(), uint32_t{8}); if (n >= num_bits) n %= num_bits; if (n == 0) return value; const auto lshift = unchecked_sub(num_bits, n); return unchecked_shr(value, n) | unchecked_shl(value, lshift); } template <class T> requires(std::is_integral_v<T> && std::is_unsigned_v<T> && ::sus::mem::size_of<T>() <= 8) __attribute__((const)) inline __attribute__((always_inline)) constexpr T swap_bytes(T value) noexcept { if (std::is_constant_evaluated()) { if constexpr (::sus::mem::size_of<T>() == 1) { return value; } else if constexpr (::sus::mem::size_of<T>() == 2) { unsigned char a = (value >> 0) & 0xff; unsigned char b = (value >> 8) & 0xff; return (a << 8) | (b << 0); } else if constexpr (::sus::mem::size_of<T>() == 4) { unsigned char a = (value >> 0) & 0xff; unsigned char b = (value >> 8) & 0xff; unsigned char c = (value >> 16) & 0xff; unsigned char d = (value >> 24) & 0xff; return (a << 24) | (b << 16) | (c << 8) | (d << 0); } else if constexpr (::sus::mem::size_of<T>() == 8) { unsigned char a = (value >> 0) & 0xff; unsigned char b = (value >> 8) & 0xff; unsigned char c = (value >> 16) & 0xff; unsigned char d = (value >> 24) & 0xff; unsigned char e = (value >> 32) & 0xff; unsigned char f = (value >> 40) & 0xff; unsigned char g = (value >> 48) & 0xff; unsigned char h = (value >> 56) & 0xff; return (a << 24) | (b << 16) | (c << 8) | (d << 0) | (e << 24) | (f << 16) | (g << 8) | (h << 0); } } if constexpr (::sus::mem::size_of<T>() == 1) { return value; } else if constexpr (::sus::mem::size_of<T>() == 2) { return __builtin_bswap16(uint16_t{value}); } else if constexpr (::sus::mem::size_of<T>() == 4) { return __builtin_bswap32(value); } else { static_assert(::sus::mem::size_of<T>() == 8); return __builtin_bswap64(value); } } template <class T> requires(std::is_integral_v<T> && std::is_signed_v<T> && ::sus::mem::size_of<T>() <= 8) __attribute__((const)) inline __attribute__((always_inline)) constexpr auto into_unsigned(T x) noexcept { if constexpr (::sus::mem::size_of<T>() == 1) return static_cast<uint8_t>(x); else if constexpr (::sus::mem::size_of<T>() == 2) return static_cast<uint16_t>(x); else if constexpr (::sus::mem::size_of<T>() == 4) return static_cast<uint32_t>(x); else return static_cast<uint64_t>(x); } template <class T> requires(std::is_integral_v<T> && !std::is_signed_v<T> && ::sus::mem::size_of<T>() <= 4) __attribute__((const)) inline __attribute__((always_inline)) constexpr auto into_widened(T x) noexcept { if constexpr (::sus::mem::size_of<T>() == 1) return static_cast<uint16_t>(x); else if constexpr (::sus::mem::size_of<T>() == 2) return static_cast<uint32_t>(x); else return static_cast<uint64_t>(x); } template <class T> requires(std::is_integral_v<T> && std::is_signed_v<T> && ::sus::mem::size_of<T>() <= 4) __attribute__((const)) inline __attribute__((always_inline)) constexpr auto into_widened(T x) noexcept { if constexpr (::sus::mem::size_of<T>() == 1) return static_cast<int16_t>(x); else if constexpr (::sus::mem::size_of<T>() == 2) return static_cast<int32_t>(x); else return static_cast<int64_t>(x); } template <class T> requires(std::is_integral_v<T> && std::is_unsigned_v<T> && ::sus::mem::size_of<T>() <= 8) __attribute__((const)) inline __attribute__((always_inline)) constexpr auto into_signed(T x) noexcept { if constexpr (::sus::mem::size_of<T>() == 1) return static_cast<int8_t>(x); else if constexpr (::sus::mem::size_of<T>() == 2) return static_cast<int16_t>(x); else if constexpr (::sus::mem::size_of<T>() == 4) return static_cast<int32_t>(x); else return static_cast<int64_t>(x); } template <class T> requires(::sus::mem::size_of<T>() <= 8) __attribute__((const)) inline __attribute__((always_inline)) constexpr bool sign_bit(T x) noexcept { if constexpr (::sus::mem::size_of<T>() == 1) return (x & (T(1) << 7)) != 0; else if constexpr (::sus::mem::size_of<T>() == 2) return (x & (T(1) << 15)) != 0; else if constexpr (::sus::mem::size_of<T>() == 4) return (x & (T(1) << 31)) != 0; else return (x & (T(1) << 63)) != 0; } template <class T> requires(std::is_integral_v<T> && !std::is_signed_v<T> && ::sus::mem::size_of<T>() <= 8) __attribute__((const)) inline constexpr OverflowOut<T> add_with_overflow(T x, T y) noexcept { return OverflowOut <T>{ .overflow = x > max_value<T>() - y, .value = unchecked_add(x, y), }; } template <class T> requires(std::is_integral_v<T> && std::is_signed_v<T> && ::sus::mem::size_of<T>() <= 8) __attribute__((const)) inline constexpr OverflowOut<T> add_with_overflow(T x, T y) noexcept { const auto out = into_signed(unchecked_add(into_unsigned(x), into_unsigned(y))); return OverflowOut <T>{ .overflow = y >= 0 != out >= x, .value = out, }; } template <class T, class U = decltype(into_signed(std::declval<T>()))> requires(std::is_integral_v<T> && !std::is_signed_v<T> && ::sus::mem::size_of<T>() <= 8 && ::sus::mem::size_of<T>() == ::sus::mem::size_of<U>()) __attribute__((const)) inline constexpr OverflowOut<T> add_with_overflow_signed( T x, U y) noexcept { return OverflowOut <T>{ .overflow = (y >= 0 && into_unsigned(y) > max_value<T>() - x) || (y < 0 && into_unsigned(-y) > x), .value = unchecked_add(x, into_unsigned(y)), }; } template <class T, class U = decltype(into_unsigned(std::declval<T>()))> requires(std::is_integral_v<T> && std::is_signed_v<T> && ::sus::mem::size_of<T>() <= 8 && ::sus::mem::size_of<T>() == ::sus::mem::size_of<U>()) __attribute__((const)) inline constexpr OverflowOut<T> add_with_overflow_unsigned( T x, U y) noexcept { const auto out = into_signed(unchecked_add(into_unsigned(x), y)); return OverflowOut <T>{ .overflow = static_cast<U>(max_value<T>()) - static_cast<U>(x) < y, .value = out, }; } template <class T> requires(std::is_integral_v<T> && !std::is_signed_v<T> && ::sus::mem::size_of<T>() <= 8) __attribute__((const)) inline constexpr OverflowOut<T> sub_with_overflow(T x, T y) noexcept { return OverflowOut <T>{ .overflow = x < unchecked_add(min_value<T>(), y), .value = unchecked_sub(x, y), }; } template <class T> requires(std::is_integral_v<T> && std::is_signed_v<T> && ::sus::mem::size_of<T>() <= 8) __attribute__((const)) inline constexpr OverflowOut<T> sub_with_overflow(T x, T y) noexcept { const auto out = into_signed(unchecked_sub(into_unsigned(x), into_unsigned(y))); return OverflowOut <T>{ .overflow = y >= 0 != out <= x, .value = out, }; } template <class T, class U = decltype(into_unsigned(std::declval<T>()))> requires(std::is_integral_v<T> && std::is_signed_v<T> && ::sus::mem::size_of<T>() <= 8 && ::sus::mem::size_of<T>() == ::sus::mem::size_of<U>()) __attribute__((const)) inline constexpr OverflowOut<T> sub_with_overflow_unsigned( T x, U y) noexcept { const auto out = into_signed(unchecked_sub(into_unsigned(x), y)); return OverflowOut <T>{ .overflow = static_cast<U>(x) - static_cast<U>(min_value<T>()) < y, .value = out, }; } template <class T> requires(std::is_integral_v<T> && std::is_signed_v<T>) __attribute__((const)) inline __attribute__((always_inline)) constexpr std::make_unsigned_t<T> sub_with_unsigned_positive_result(T x, T y) noexcept { return unchecked_sub(into_unsigned(x), into_unsigned(y)); } template <class T> requires(std::is_integral_v<T> && !std::is_signed_v<T> && ::sus::mem::size_of<T>() <= 4) __attribute__((const)) inline constexpr OverflowOut<T> mul_with_overflow(T x, T y) noexcept { auto out = unchecked_mul(into_widened(x), into_widened(y)); using Wide = decltype(out); return OverflowOut <T>{ .overflow = out > Wide{max_value<T>()}, .value = static_cast<T>(out)}; } template <class T> requires(std::is_integral_v<T> && !std::is_signed_v<T> && ::sus::mem::size_of<T>() == 8) __attribute__((const)) inline constexpr OverflowOut<T> mul_with_overflow(T x, T y) noexcept { auto out = __uint128_t{x} * __uint128_t{y}; return OverflowOut <T>{ .overflow = out > __uint128_t{max_value<T>()}, .value = static_cast<T>(out)}; } template <class T> requires(std::is_integral_v<T> && std::is_signed_v<T> && ::sus::mem::size_of<T>() <= 4) __attribute__((const)) inline constexpr OverflowOut<T> mul_with_overflow(T x, T y) noexcept { auto out = into_widened(x) * into_widened(y); using Wide = decltype(out); return OverflowOut <T>{ .overflow = out > Wide{max_value<T>()} || out < Wide{min_value<T>()}, .value = static_cast<T>(out)}; } template <class T> requires(std::is_integral_v<T> && std::is_signed_v<T> && ::sus::mem::size_of<T>() == 8) __attribute__((const)) inline constexpr OverflowOut<T> mul_with_overflow(T x, T y) noexcept { auto out = __int128_t{x} * __int128_t{y}; return OverflowOut <T>{ .overflow = out > __int128_t{max_value<T>()} || out < __int128_t{min_value<T>()}, .value = static_cast<T>(out)}; } template <class T> requires(std::is_integral_v<T> && ::sus::mem::size_of<T>() <= 8) __attribute__((const)) inline constexpr OverflowOut<T> pow_with_overflow( T base, uint32_t exp) noexcept { if (exp == 0) return OverflowOut <T>{.overflow = false, .value = T{1}}; auto acc = T{1}; bool overflow = false; while (exp > 1) { if (exp & 1) { auto r = mul_with_overflow(acc, base); overflow |= r.overflow; acc = r.value; } exp /= 2; auto r = mul_with_overflow(base, base); overflow |= r.overflow; base = r.value; } auto r = mul_with_overflow(acc, base); return OverflowOut <T>{ .overflow = overflow || r.overflow, .value = r.value}; } template <class T> requires(std::is_integral_v<T> && !std::is_signed_v<T> && (::sus::mem::size_of<T>() == 1 || ::sus::mem::size_of<T>() == 2 || ::sus::mem::size_of<T>() == 4 || ::sus::mem::size_of<T>() == 8)) __attribute__((const)) inline constexpr OverflowOut<T> shl_with_overflow( T x, uint32_t shift) noexcept { const bool overflow = shift >= num_bits<T>(); if (overflow) [[unlikely]] shift = shift & (unchecked_sub(num_bits<T>(), uint32_t{1})); return OverflowOut <T>{.overflow = overflow, .value = unchecked_shl(x, shift)}; } template <class T> requires(std::is_integral_v<T> && std::is_signed_v<T> && (::sus::mem::size_of<T>() == 1 || ::sus::mem::size_of<T>() == 2 || ::sus::mem::size_of<T>() == 4 || ::sus::mem::size_of<T>() == 8)) __attribute__((const)) inline constexpr OverflowOut<T> shl_with_overflow( T x, uint32_t shift) noexcept { const bool overflow = shift >= num_bits<T>(); if (overflow) [[unlikely]] shift = shift & (unchecked_sub(num_bits<T>(), uint32_t{1})); return OverflowOut <T>{ .overflow = overflow, .value = into_signed(unchecked_shl(into_unsigned(x), shift))}; } template <class T> requires(std::is_integral_v<T> && !std::is_signed_v<T> && (::sus::mem::size_of<T>() == 1 || ::sus::mem::size_of<T>() == 2 || ::sus::mem::size_of<T>() == 4 || ::sus::mem::size_of<T>() == 8)) __attribute__((const)) inline constexpr OverflowOut<T> shr_with_overflow( T x, uint32_t shift) noexcept { const bool overflow = shift >= num_bits<T>(); if (overflow) [[unlikely]] shift = shift & (unchecked_sub(num_bits<T>(), uint32_t{1})); return OverflowOut <T>{.overflow = overflow, .value = unchecked_shr(x, shift)}; } template <class T> requires(std::is_integral_v<T> && std::is_signed_v<T> && (::sus::mem::size_of<T>() == 1 || ::sus::mem::size_of<T>() == 2 || ::sus::mem::size_of<T>() == 4 || ::sus::mem::size_of<T>() == 8)) __attribute__((const)) inline constexpr OverflowOut<T> shr_with_overflow( T x, uint32_t shift) noexcept { const bool overflow = shift >= num_bits<T>(); if (overflow) [[unlikely]] shift = shift & (unchecked_sub(num_bits<T>(), uint32_t{1})); return OverflowOut <T>{ .overflow = overflow, .value = into_signed(unchecked_shr(into_unsigned(x), shift))}; } template <class T> requires(std::is_integral_v<T> && !std::is_signed_v<T> && ::sus::mem::size_of<T>() <= 8) __attribute__((const)) inline constexpr T saturating_add(T x, T y) noexcept { const auto out = add_with_overflow(x, y); if (!out.overflow) [[likely]] return out.value; else return max_value<T>(); } template <class T> requires(std::is_integral_v<T> && std::is_signed_v<T> && ::sus::mem::size_of<T>() <= 8) __attribute__((const)) inline constexpr T saturating_add(T x, T y) noexcept { if (y >= 0) { if (x <= max_value<T>() - y) [[likely]] return x + y; else return max_value<T>(); } else { if (x >= min_value<T>() - y) [[likely]] return x + y; else return min_value<T>(); } } template <class T> requires(std::is_integral_v<T> && !std::is_signed_v<T> && ::sus::mem::size_of<T>() <= 8) __attribute__((const)) inline constexpr T saturating_sub(T x, T y) noexcept { const auto out = sub_with_overflow(x, y); if (!out.overflow) [[likely]] return out.value; else return min_value<T>(); } template <class T> requires(std::is_integral_v<T> && std::is_signed_v<T> && ::sus::mem::size_of<T>() <= 8) __attribute__((const)) inline constexpr T saturating_sub(T x, T y) noexcept { if (y <= 0) { if (x <= max_value<T>() + y) [[likely]] return x - y; else return max_value<T>(); } else { if (x >= min_value<T>() + y) [[likely]] return x - y; else return min_value<T>(); } } template <class T> requires(std::is_integral_v<T> && !std::is_signed_v<T> && ::sus::mem::size_of<T>() <= 8) __attribute__((const)) inline constexpr T saturating_mul(T x, T y) noexcept { const auto out = mul_with_overflow(x, y); if (!out.overflow) [[likely]] return out.value; else return max_value<T>(); } template <class T> requires(std::is_integral_v<T> && std::is_signed_v<T> && ::sus::mem::size_of<T>() <= 8) __attribute__((const)) inline constexpr T saturating_mul(T x, T y) noexcept { const auto out = mul_with_overflow(x, y); if (!out.overflow) [[likely]] return out.value; else if (x > 0 == y > 0) return max_value<T>(); else return min_value<T>(); } template <class T> requires(std::is_integral_v<T> && !std::is_signed_v<T> && ::sus::mem::size_of<T>() <= 8) __attribute__((const)) inline __attribute__((always_inline)) constexpr T wrapping_add(T x, T y) noexcept { return x + y; } template <class T> requires(std::is_integral_v<T> && std::is_signed_v<T> && ::sus::mem::size_of<T>() <= 8) __attribute__((const)) inline __attribute__((always_inline)) constexpr T wrapping_add(T x, T y) noexcept { return add_with_overflow(x, y).value; } template <class T> requires(std::is_integral_v<T> && !std::is_signed_v<T> && ::sus::mem::size_of<T>() <= 8) __attribute__((const)) inline __attribute__((always_inline)) constexpr T wrapping_sub(T x, T y) noexcept { return unchecked_sub(x, y); } template <class T> requires(std::is_integral_v<T> && std::is_signed_v<T> && ::sus::mem::size_of<T>() <= 8) __attribute__((const)) inline __attribute__((always_inline)) constexpr T wrapping_sub(T x, T y) noexcept { return sub_with_overflow(x, y).value; } template <class T> requires(std::is_integral_v<T> && !std::is_signed_v<T> && ::sus::mem::size_of<T>() <= 8) __attribute__((const)) inline __attribute__((always_inline)) constexpr T wrapping_mul(T x, T y) noexcept { return x * y; } template <class T> requires(std::is_integral_v<T> && std::is_signed_v<T> && ::sus::mem::size_of<T>() <= 8) __attribute__((const)) inline __attribute__((always_inline)) constexpr T wrapping_mul(T x, T y) noexcept { return mul_with_overflow(x, y).value; } template <class T> requires(std::is_integral_v<T> && !std::is_signed_v<T> && ::sus::mem::size_of<T>() <= 8) __attribute__((const)) inline __attribute__((always_inline)) constexpr T wrapping_pow( T base, uint32_t exp) noexcept { return pow_with_overflow(base, exp).value; } template <class T> requires(std::is_integral_v<T> && std::is_signed_v<T> && ::sus::mem::size_of<T>() <= 8) __attribute__((const)) inline __attribute__((always_inline)) constexpr T wrapping_pow( T base, uint32_t exp) noexcept { return pow_with_overflow(base, exp).value; } template <class T> requires(std::is_integral_v<T> && !std::is_signed_v<T> && ::sus::mem::size_of<T>() <= 8) __attribute__((const)) inline constexpr T one_less_than_next_power_of_two( T x) noexcept { if (x <= 1u) { return 0u; } else { const auto p = unchecked_sub(x, T{1}); const auto z = leading_zeros_nonzero(::sus::marker::unsafe_fn, p); return unchecked_shr(max_value<T>(), z); } } template <class T> requires(std::is_integral_v<T> && std::is_signed_v<T> && ::sus::mem::size_of<T>() <= 8) __attribute__((const)) inline constexpr bool div_overflows(T x, T y) noexcept { return y == T{0} || ((x == min_value<T>()) & (y == T{-1})); } template <class T> requires(std::is_integral_v<T> && std::is_signed_v<T> && ::sus::mem::size_of<T>() <= 8) __attribute__((const)) inline constexpr bool div_overflows_nonzero( ::sus::marker::UnsafeFnMarker, T x, T y) noexcept { return ((x == min_value<T>()) & (y == T{-1})); } template <class T> requires(std::is_integral_v<T> && std::is_signed_v<T> && ::sus::mem::size_of<T>() <= 8) __attribute__((const)) inline constexpr T div_euclid(::sus::marker::UnsafeFnMarker, T x, T y) noexcept { const auto q = unchecked_div(x, y); if (x % y >= 0) return q; else if (y > 0) return unchecked_sub(q, T{1}); else return unchecked_add(q, T{1}); } template <class T> requires(std::is_integral_v<T> && std::is_signed_v<T> && ::sus::mem::size_of<T>() <= 8) __attribute__((const)) inline constexpr T rem_euclid(::sus::marker::UnsafeFnMarker, T x, T y) noexcept { const auto r = unchecked_rem(x, y); if (r < 0) { if (y < 0) return unchecked_sub(r, y); else return unchecked_add(r, y); } else { return r; } } template <class T> requires(std::is_floating_point_v<T> && ::sus::mem::size_of<T>() <= 8) __attribute__((const)) inline __attribute__((always_inline)) constexpr auto into_unsigned_integer( T x) noexcept { if constexpr (::sus::mem::size_of<T>() == ::sus::mem::size_of<float>()) return std::bit_cast<uint32_t>(x); else return std::bit_cast<uint64_t>(x); } template <class T> requires(std::is_integral_v<T> && ::sus::mem::size_of<T>() <= 8) __attribute__((const)) inline __attribute__((always_inline)) constexpr auto into_float_constexpr( ::sus::marker::UnsafeFnMarker, T x) noexcept { if constexpr (::sus::mem::size_of<T>() == ::sus::mem::size_of<float>()) return std::bit_cast<float>(x); else return std::bit_cast<double>(x); } template <class T> requires(std::is_integral_v<T> && ::sus::mem::size_of<T>() <= 8) __attribute__((const)) inline __attribute__((always_inline)) auto into_float(T x) noexcept { return into_float_constexpr(::sus::marker::unsafe_fn, x); } template <class T> requires(std::is_floating_point_v<T>) __attribute__((const)) inline __attribute__((always_inline)) constexpr T min_positive_value() noexcept { if constexpr (::sus::mem::size_of<T>() == ::sus::mem::size_of<float>()) return 1.17549435E-38f; else return 0.22250738585072014E-307; } template <class T> requires(std::is_floating_point_v<T>) __attribute__((const)) inline __attribute__((always_inline)) constexpr int32_t min_exp() noexcept { if constexpr (::sus::mem::size_of<T>() == ::sus::mem::size_of<float>()) return int32_t{-125}; else return int32_t{-1021}; } template <class T> requires(std::is_floating_point_v<T>) __attribute__((const)) inline __attribute__((always_inline)) constexpr int32_t max_exp() noexcept { if constexpr (::sus::mem::size_of<T>() == ::sus::mem::size_of<float>()) return int32_t{128}; else return int32_t{1024}; } template <class T> requires(std::is_floating_point_v<T>) __attribute__((const)) inline __attribute__((always_inline)) constexpr int32_t min_10_exp() noexcept { if constexpr (::sus::mem::size_of<T>() == ::sus::mem::size_of<float>()) return int32_t{-37}; else return int32_t{-307}; } template <class T> requires(std::is_floating_point_v<T>) __attribute__((const)) inline __attribute__((always_inline)) constexpr int32_t max_10_exp() noexcept { if constexpr (::sus::mem::size_of<T>() == ::sus::mem::size_of<float>()) return int32_t{38}; else return int32_t{308}; } template <class T> requires(std::is_floating_point_v<T>) __attribute__((const)) inline __attribute__((always_inline)) constexpr uint32_t radix() noexcept { return 2; } template <class T> requires(std::is_floating_point_v<T>) __attribute__((const)) inline __attribute__((always_inline)) constexpr uint32_t num_mantissa_digits() noexcept { if constexpr (::sus::mem::size_of<T>() == ::sus::mem::size_of<float>()) return uint32_t{24}; else return uint32_t{53}; } template <class T> requires(std::is_floating_point_v<T>) __attribute__((const)) inline __attribute__((always_inline)) constexpr uint32_t num_digits() noexcept { if constexpr (::sus::mem::size_of<T>() == ::sus::mem::size_of<float>()) return 6; else return 15; } template <class T> requires(std::is_floating_point_v<T>) __attribute__((const)) inline __attribute__((always_inline)) constexpr T nan() noexcept { if constexpr (::sus::mem::size_of<T>() == ::sus::mem::size_of<float>()) return into_float_constexpr(::sus::marker::unsafe_fn, uint32_t{0x7fc00000}); else return into_float_constexpr(::sus::marker::unsafe_fn, uint64_t{0x7ff8000000000000}); } template <class T> requires(std::is_floating_point_v<T>) __attribute__((const)) inline __attribute__((always_inline)) constexpr T infinity() noexcept { if constexpr (::sus::mem::size_of<T>() == ::sus::mem::size_of<float>()) return into_float_constexpr(::sus::marker::unsafe_fn, uint32_t{0x7f800000}); else return into_float_constexpr(::sus::marker::unsafe_fn, uint64_t{0x7ff0000000000000}); } template <class T> requires(std::is_floating_point_v<T>) __attribute__((const)) inline __attribute__((always_inline)) constexpr T negative_infinity() noexcept { if constexpr (::sus::mem::size_of<T>() == ::sus::mem::size_of<float>()) return into_float_constexpr(::sus::marker::unsafe_fn, uint32_t{0xff800000}); else return into_float_constexpr(::sus::marker::unsafe_fn, uint64_t{0xfff0000000000000}); } __attribute__((const)) inline __attribute__((always_inline)) constexpr int32_t exponent_bits( float x) noexcept { constexpr uint32_t mask = 0b01111111100000000000000000000000; return static_cast<int32_t>( unchecked_shr(into_unsigned_integer(x) & mask, 23)); } __attribute__((const)) inline __attribute__((always_inline)) constexpr int32_t exponent_bits( double x) noexcept { constexpr uint64_t mask = 0b0111111111110000000000000000000000000000000000000000000000000000; return static_cast<int32_t>( unchecked_shr(into_unsigned_integer(x) & mask, 52)); } __attribute__((const)) inline __attribute__((always_inline)) constexpr int32_t float_normal_exponent_value( float x) noexcept { return exponent_bits(x) - int32_t{127}; } __attribute__((const)) inline __attribute__((always_inline)) constexpr int32_t float_normal_exponent_value( double x) noexcept { return exponent_bits(x) - int32_t{1023}; } constexpr inline __attribute__((always_inline)) uint32_t mantissa(float x) noexcept { constexpr uint32_t mask = 0b00000000011111111111111111111111; return into_unsigned_integer(x) & mask; } __attribute__((const)) inline __attribute__((always_inline)) constexpr uint64_t mantissa( double x) noexcept { constexpr uint64_t mask = 0b0000000000001111111111111111111111111111111111111111111111111111; return into_unsigned_integer(x) & mask; } template <class T> requires(std::is_floating_point_v<T> && ::sus::mem::size_of<T>() <= 8) __attribute__((const)) inline __attribute__((always_inline)) constexpr bool float_is_zero(T x) noexcept { return (into_unsigned_integer(x) & ~high_bit<T>()) == 0; } __attribute__((const)) inline constexpr bool float_is_inf(float x) noexcept { return __builtin_isinf(x); } __attribute__((const)) inline constexpr bool float_is_inf(double x) noexcept { return __builtin_isinf(x); } __attribute__((const)) inline constexpr bool float_is_inf_or_nan(float x) noexcept { constexpr auto mask = uint32_t{0x7f800000}; return (into_unsigned_integer(x) & mask) == mask; } __attribute__((const)) inline constexpr bool float_is_inf_or_nan(double x) noexcept { constexpr auto mask = uint64_t{0x7ff0000000000000}; return (into_unsigned_integer(x) & mask) == mask; } __attribute__((const)) inline constexpr bool float_is_nan(float x) noexcept { return __builtin_isnan(x); } __attribute__((const)) inline constexpr bool float_is_nan(double x) noexcept { return __builtin_isnan(x); } __attribute__((const)) inline constexpr bool float_is_nan_quiet(float x) noexcept { constexpr auto quiet_mask = uint32_t{uint32_t{1} << (23 - 1)}; return (into_unsigned_integer(x) & quiet_mask) != 0; } __attribute__((const)) inline constexpr bool float_is_nan_quiet(double x) noexcept { constexpr auto quiet_mask = uint64_t{uint64_t{1} << (52 - 1)}; return (into_unsigned_integer(x) & quiet_mask) != 0; } template <class T> requires(std::is_floating_point_v<T> && ::sus::mem::size_of<T>() <= 8) __attribute__((const)) inline __attribute__((always_inline)) constexpr bool float_nonzero_is_subnormal( T x) noexcept { return exponent_bits(x) == int32_t{0}; } __attribute__((const)) inline constexpr bool float_is_normal(float x) noexcept { const auto e = exponent_bits(x); return e != 0 && e != int32_t{0b011111111}; } __attribute__((const)) inline constexpr bool float_is_normal(double x) noexcept { const auto e = exponent_bits(x); return e != 0 && e != int32_t{0b011111111111}; } template <class T> requires(std::is_floating_point_v<T> && ::sus::mem::size_of<T>() <= 8) __attribute__((const)) inline constexpr T truncate_float(T x) noexcept { if constexpr (::sus::mem::size_of<T>() == 4) { constexpr float max_i64 = 9223371487098961920.f; constexpr float min_i64 = -9223372036854775808.f; if (x <= max_i64 && x >= min_i64) return static_cast<T>(static_cast<int64_t>(x)); } else { constexpr double max_i64 = 9223372036854774784.0; constexpr float min_i64 = -9223372036854775808.0; if (x <= max_i64 && x >= min_i64) return static_cast<T>(static_cast<int64_t>(x)); } constexpr auto mantissa_width = ::sus::mem::size_of<T>() == ::sus::mem::size_of<float>() ? uint32_t{23} : uint32_t{52}; if (float_is_inf_or_nan(x) || float_is_zero(x)) return x; if (float_nonzero_is_subnormal(x)) [[unlikely]] return T{0}; const int32_t exponent = float_normal_exponent_value(x); if (exponent >= static_cast<int32_t>(mantissa_width)) return x; if (exponent <= -1) { if ((into_unsigned_integer(x) & high_bit<T>()) != 0) return T{-0.0}; else return T{0.0}; } const uint32_t trim_bits = mantissa_width - static_cast<uint32_t>(exponent); const auto shr = unchecked_shr(into_unsigned_integer(x), trim_bits); const auto shl = unchecked_shl(shr, trim_bits); return into_float_constexpr(::sus::marker::unsafe_fn, shl); } template <class T> requires(std::is_floating_point_v<T> && ::sus::mem::size_of<T>() <= 8) __attribute__((const)) inline constexpr bool float_signbit(T x) noexcept { return unchecked_and(into_unsigned_integer(x), high_bit<T>()) != 0; } template <class T> requires(std::is_floating_point_v<T> && ::sus::mem::size_of<T>() <= 8) __attribute__((const)) inline constexpr T float_signum(T x) noexcept { if (float_is_nan(x)) [[unlikely]] return x; const auto signbit = unchecked_and(into_unsigned_integer(x), high_bit<T>()); return into_float_constexpr( ::sus::marker::unsafe_fn, unchecked_add(into_unsigned_integer(T{1}), signbit)); } template <class T> requires(std::is_floating_point_v<T> && ::sus::mem::size_of<T>() <= 8) __attribute__((const)) inline T float_round(T x) noexcept { const auto out = into_unsigned_integer(static_cast<T>(::round(x))); return into_float((out & ~high_bit<T>()) | (into_unsigned_integer(x) & high_bit<T>())); } template <class T> requires(std::is_floating_point_v<T> && ::sus::mem::size_of<T>() <= 8) constexpr inline ::sus::num::FpCategory float_category(T x) noexcept { constexpr auto nan = 1; constexpr auto inf = 2; constexpr auto norm = 3; constexpr auto subnorm = 4; constexpr auto zero = 5; switch (__builtin_fpclassify(nan, inf, norm, subnorm, zero, x)) { case nan: return ::sus::num::FpCategory::Nan; case inf: return ::sus::num::FpCategory::Infinite; case norm: return ::sus::num::FpCategory::Normal; case subnorm: return ::sus::num::FpCategory::Subnormal; case zero: return ::sus::num::FpCategory::Zero; default: ::sus::unreachable_unchecked(::sus::marker::unsafe_fn); } } template <class T> requires(std::is_floating_point_v<T> && ::sus::mem::size_of<T>() <= 8) __attribute__((const)) constexpr inline T float_clamp(marker::UnsafeFnMarker, T x, T min, T max) noexcept { if (float_is_nan(x)) [[unlikely]] return nan<T>(); else if (x < min) return min; else if (x > max) return max; return x; } template <class T> requires(std::is_floating_point_v<T> && ::sus::mem::size_of<T>() <= 8) __attribute__((const)) inline T next_toward(T from, T to) { if constexpr (::sus::mem::size_of<T>() == 4u) return std::nexttowardf(from, to); else return std::nexttoward(from, to); } #pragma warning(push) #pragma warning(disable : 4756) template <class Out, class T> requires(std::is_integral_v<T> && std::is_floating_point_v<Out> && (::sus::mem::size_of<T>() <= 8) && (::sus::mem::size_of<Out>() == 4 || ::sus::mem::size_of<Out>() == 8)) __attribute__((const)) constexpr inline Out static_cast_int_to_float(T x) noexcept { return static_cast<Out>(x); } template <class Out, class T> requires(std::is_floating_point_v<T> && std::is_floating_point_v<Out> && ::sus::mem::size_of<T>() == 8 && ::sus::mem::size_of<Out>() == 4) __attribute__((const)) constexpr inline Out static_cast_to_smaller_float(T x) noexcept { if (x <= T{max_value<Out>()} && x >= T{min_value<Out>()}) [[likely]] { return static_cast<Out>(x); } if (x > T{max_value<Out>()}) { return infinity<Out>(); } if (x < T{min_value<Out>()}) { return negative_infinity<Out>(); } return nan<Out>(); } #pragma warning(pop) } namespace sus::num::__private { template <unsigned int bytes = ::sus::mem::size_of<void*>()> struct ptr_type; template <> struct ptr_type<4> { using unsigned_type = uint32_t; using signed_type = int32_t; }; template <> struct ptr_type<8> { using unsigned_type = uint64_t; using signed_type = int64_t; }; template <unsigned int bytes = ::sus::mem::size_of<size_t>()> struct addr_type; template <> struct addr_type<4> { using unsigned_type = uint32_t; using signed_type = int32_t; }; template <> struct addr_type<8> { using unsigned_type = uint64_t; using signed_type = int64_t; }; } namespace sus::num { template <class T> concept Float = std::same_as<f32, T> || std::same_as<f64, T>; template <class T> concept PrimitiveFloat = std::same_as<float, T> || std::same_as<double, T> || std::same_as<long double, T>; } namespace sus::num { template <class T> concept Unsigned = std::same_as<u8, T> || std::same_as<u16, T> || std::same_as<u32, T> || std::same_as<u64, T> || std::same_as<usize, T> || std::same_as<uptr, T>; template <class T> concept Signed = std::same_as<i8, T> || std::same_as<i16, T> || std::same_as<i32, T> || std::same_as<i64, T> || std::same_as<isize, T>; template <class T> concept Integer = Unsigned<T> || Signed<T>; template <class T> concept UnsignedPrimitiveInteger = std::same_as<size_t, T> || std::same_as<uintptr_t, T> || std::same_as<bool, T> || (std::is_unsigned_v<char> && std::same_as<char, T>) || std::same_as<unsigned char, T> || std::same_as<unsigned short, T> || std::same_as<unsigned int, T> || std::same_as<unsigned long, T> || std::same_as<unsigned long long, T>; template <class T> concept SignedPrimitiveInteger = (!std::is_unsigned_v<char> && std::same_as<char, T>) || std::same_as<signed char, T> || std::same_as<short, T> || std::same_as<int, T> || std::same_as<long, T> || std::same_as<long long, T>; template <class T> concept PrimitiveInteger = UnsignedPrimitiveInteger<T> || SignedPrimitiveInteger<T>; template <class T> concept UnsignedPrimitiveEnum = std::is_enum_v<T> && UnsignedPrimitiveInteger<std::underlying_type_t<T>> && std::is_convertible_v<T, std::underlying_type_t<T>>; template <class T> concept SignedPrimitiveEnum = std::is_enum_v<T> && SignedPrimitiveInteger<std::underlying_type_t<T>> && std::is_convertible_v<T, std::underlying_type_t<T>>; template <class T> concept PrimitiveEnum = UnsignedPrimitiveEnum<T> || SignedPrimitiveEnum<T>; template <class T> concept UnsignedPrimitiveEnumClass = !UnsignedPrimitiveEnum<T> && std::is_enum_v<T> && UnsignedPrimitiveInteger<std::underlying_type_t<T>>; template <class T> concept SignedPrimitiveEnumClass = !SignedPrimitiveEnum<T> && std::is_enum_v<T> && SignedPrimitiveInteger<std::underlying_type_t<T>>; template <class T> concept PrimitiveEnumClass = UnsignedPrimitiveEnumClass<T> || SignedPrimitiveEnumClass<T>; } namespace sus::num { class TryFromIntError { public: enum class Kind { OutOfBounds, }; constexpr static TryFromIntError with_out_of_bounds() noexcept { return TryFromIntError(CONSTRUCT, Kind::OutOfBounds); } __attribute__((pure)) constexpr Kind kind() const noexcept { return kind_; } __attribute__((pure)) constexpr bool operator==(TryFromIntError rhs) const noexcept { return kind_ == rhs.kind_; } private: enum Construct { CONSTRUCT }; constexpr inline explicit TryFromIntError(Construct, Kind k) noexcept : kind_(k) {} Kind kind_; }; } namespace sus::num { struct u32 final { uint32_t primitive_value{0u}; static constexpr auto MIN_PRIMITIVE = __private::min_value<uint32_t>(); static constexpr auto MAX_PRIMITIVE = __private::max_value<uint32_t>(); static const u32 MIN; static const u32 MAX; static const u32 BITS; constexpr inline u32() noexcept = default; template <Unsigned U> requires(::sus::mem::size_of<U>() <= ::sus::mem::size_of<uint32_t>()) constexpr inline u32(U v) noexcept : primitive_value(v.primitive_value) {} template <UnsignedPrimitiveInteger P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of<uint32_t>()) constexpr inline u32(P v) noexcept : primitive_value(v) {} template <UnsignedPrimitiveEnum P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of<uint32_t>()) constexpr inline u32(P v) noexcept : primitive_value(v) {} template <UnsignedPrimitiveEnumClass P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of<uint32_t>()) explicit constexpr inline u32(P v) noexcept : primitive_value(static_cast<uint32_t>(v)) {} template <Unsigned U> requires(::sus::mem::size_of<U>() <= ::sus::mem::size_of<uint32_t>()) constexpr inline u32& operator=(U v) noexcept { primitive_value = v.primitive_value; return *this; } template <UnsignedPrimitiveInteger P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of<uint32_t>()) constexpr inline u32& operator=(P v) noexcept { primitive_value = v; return *this; } template <UnsignedPrimitiveEnum P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of<uint32_t>()) constexpr inline u32& operator=(P v) noexcept { primitive_value = static_cast<uint32_t>(v); return *this; } template <Unsigned U> requires(::sus::mem::size_of<U>() <= ::sus::mem::size_of<uint32_t>()) __attribute__((pure)) static constexpr u32 from(U u) noexcept { return u32(static_cast<uint32_t>(u.primitive_value)); } template <Unsigned U> __attribute__((pure)) static constexpr ::sus::result::Result<u32, ::sus::num::TryFromIntError> try_from(U u) noexcept; template <UnsignedPrimitiveInteger U> requires(::sus::mem::size_of<U>() <= ::sus::mem::size_of<uint32_t>()) __attribute__((pure)) static constexpr u32 from(U u) noexcept { return u32(static_cast<uint32_t>(u)); } template <UnsignedPrimitiveInteger U> __attribute__((pure)) static constexpr ::sus::result::Result<u32, ::sus::num::TryFromIntError> try_from(U u) noexcept; template <Signed S> __attribute__((pure)) static constexpr ::sus::result::Result<u32, ::sus::num::TryFromIntError> try_from(S s) noexcept; template <SignedPrimitiveInteger S> __attribute__((pure)) static constexpr ::sus::result::Result<u32, ::sus::num::TryFromIntError> try_from(S s) noexcept; template <class S> requires(SignedPrimitiveEnum<S> || SignedPrimitiveEnumClass<S>) __attribute__((pure)) static constexpr ::sus::result::Result<u32, ::sus::num::TryFromIntError> try_from(S s) noexcept; template <class U> requires((UnsignedPrimitiveEnum<U> || UnsignedPrimitiveEnumClass<U>) && ::sus::mem::size_of<U>() <= ::sus::mem::size_of<uint32_t>()) __attribute__((pure)) static constexpr u32 from(U u) noexcept { return u32(static_cast<std::underlying_type_t<U>>(u)); } template <class U> requires(UnsignedPrimitiveEnum<U> || UnsignedPrimitiveEnumClass<U>) __attribute__((pure)) static constexpr ::sus::result::Result<u32, ::sus::num::TryFromIntError> try_from(U u) noexcept; static constexpr u32 from_product( ::sus::iter::Iterator<u32> auto&& it) noexcept { auto p = u32(uint32_t{1u}); for (u32 i : ::sus::move(it)) p *= i; return p; } static constexpr u32 from_sum( ::sus::iter::Iterator<u32> auto&& it) noexcept { auto p = u32(uint32_t{0u}); for (u32 i : ::sus::move(it)) p += i; return p; } template <UnsignedPrimitiveInteger U> requires(::sus::mem::size_of<U>() >= ::sus::mem::size_of<uint32_t>()) __attribute__((pure)) constexpr inline explicit operator U() const { return primitive_value; } [[nodiscard]] __attribute__((pure)) friend constexpr inline bool operator==( const u32& l, const u32& r) noexcept = default; template <UnsignedPrimitiveInteger P> [[nodiscard]] __attribute__((pure)) friend constexpr inline bool operator==( const u32& l, const P& r) noexcept { return l.primitive_value == r; } template <Unsigned U> [[nodiscard]] __attribute__((pure)) friend constexpr inline bool operator==( const u32& l, const U& r) noexcept { return l.primitive_value == r.primitive_value; } template <UnsignedPrimitiveInteger P> [[nodiscard]] __attribute__((pure)) friend constexpr inline std::strong_ordering operator<=>( const u32& l, const u32& r) noexcept { return l.primitive_value <=> r.primitive_value; } template <UnsignedPrimitiveInteger P> [[nodiscard]] __attribute__((pure)) friend constexpr inline std::strong_ordering operator<=>( const u32& l, const P& r) noexcept { return l.primitive_value <=> r; } template <Unsigned U> [[nodiscard]] __attribute__((pure)) friend constexpr inline std::strong_ordering operator<=>( const u32& l, const U& r) noexcept { return l.primitive_value <=> r.primitive_value; } __attribute__((pure)) constexpr inline u32 operator~() const& noexcept { return u32(__private::unchecked_not(primitive_value)); } [[nodiscard]] __attribute__((pure)) friend constexpr inline u32 operator+( const u32& l, const u32& r) noexcept { const auto out = __private::add_with_overflow(l.primitive_value, r.primitive_value); ::sus::check(!out.overflow); return u32(out.value); } [[nodiscard]] __attribute__((pure)) friend constexpr inline u32 operator-( const u32& l, const u32& r) noexcept { const auto out = __private::sub_with_overflow(l.primitive_value, r.primitive_value); ::sus::check(!out.overflow); return u32(out.value); } [[nodiscard]] __attribute__((pure)) friend constexpr inline u32 operator*( const u32& l, const u32& r) noexcept { const auto out = __private::mul_with_overflow(l.primitive_value, r.primitive_value); ::sus::check(!out.overflow); return u32(out.value); } [[nodiscard]] __attribute__((pure)) friend constexpr inline u32 operator/( const u32& l, const u32& r) noexcept { ::sus::check(r.primitive_value != 0u); return u32(__private::unchecked_div(l.primitive_value, r.primitive_value)); } [[nodiscard]] __attribute__((pure)) friend constexpr inline u32 operator%( const u32& l, const u32& r) noexcept { ::sus::check(r.primitive_value != 0u); return u32(__private::unchecked_rem(l.primitive_value, r.primitive_value)); } [[nodiscard]] __attribute__((pure)) friend constexpr inline u32 operator&( const u32& l, const u32& r) noexcept { return u32(__private::unchecked_and(l.primitive_value, r.primitive_value)); } [[nodiscard]] __attribute__((pure)) friend constexpr inline u32 operator|( const u32& l, const u32& r) noexcept { return u32(__private::unchecked_or(l.primitive_value, r.primitive_value)); } [[nodiscard]] __attribute__((pure)) friend constexpr inline u32 operator^( const u32& l, const u32& r) noexcept { return u32(__private::unchecked_xor(l.primitive_value, r.primitive_value)); } [[nodiscard]] __attribute__((pure)) friend constexpr inline u32 operator<<( const u32& l, const u32& r) noexcept { ::sus::check(r < BITS); return u32(__private::unchecked_shl(l.primitive_value, r.primitive_value)); } [[nodiscard]] __attribute__((pure)) friend constexpr inline u32 operator>>( const u32& l, const u32& r) noexcept { ::sus::check(r < BITS); return u32(__private::unchecked_shr(l.primitive_value, r.primitive_value)); } constexpr inline void operator+=(u32 r) & noexcept { const auto out = __private::add_with_overflow(primitive_value, r.primitive_value); ::sus::check(!out.overflow); primitive_value = out.value; } constexpr inline void operator-=(u32 r) & noexcept { const auto out = __private::sub_with_overflow(primitive_value, r.primitive_value); ::sus::check(!out.overflow); primitive_value = out.value; } constexpr inline void operator*=(u32 r) & noexcept { const auto out = __private::mul_with_overflow(primitive_value, r.primitive_value); ::sus::check(!out.overflow); primitive_value = out.value; } constexpr inline void operator/=(u32 r) & noexcept { ::sus::check(r.primitive_value != 0u); primitive_value /= r.primitive_value; } constexpr inline void operator%=(u32 r) & noexcept { ::sus::check(r.primitive_value != 0u); primitive_value %= r.primitive_value; } constexpr inline void operator&=(u32 r) & noexcept { primitive_value &= r.primitive_value; } constexpr inline void operator|=(u32 r) & noexcept { primitive_value |= r.primitive_value; } constexpr inline void operator^=(u32 r) & noexcept { primitive_value ^= r.primitive_value; } constexpr inline void operator<<=(const u32& r) & noexcept { ::sus::check(r < BITS); primitive_value <<= r.primitive_value; } constexpr inline void operator>>=(const u32& r) & noexcept { ::sus::check(r < BITS); primitive_value >>= r.primitive_value; } __attribute__((pure)) constexpr u32 abs_diff(const u32& r) const& noexcept { if (primitive_value >= r.primitive_value) return u32(__private::unchecked_sub(primitive_value, r.primitive_value)); else return u32(__private::unchecked_sub(r.primitive_value, primitive_value)); } __attribute__((pure)) constexpr ::sus::option::Option<u32> checked_add( const u32& rhs) const& noexcept; template <std::convertible_to<i32> S> __attribute__((pure)) constexpr ::sus::option::Option<u32> checked_add_signed( const S& rhs) const& noexcept; __attribute__((pure)) constexpr sus::tuple_type::Tuple<u32, bool> overflowing_add( const u32& rhs) const& noexcept; template <std::convertible_to<i32> S> __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u32, bool> overflowing_add_signed( const S& rhs) const& noexcept; __attribute__((pure)) constexpr u32 saturating_add(const u32& rhs) const& noexcept { return u32(__private::saturating_add(primitive_value, rhs.primitive_value)); } template <std::convertible_to<i32> S> __attribute__((pure)) constexpr u32 saturating_add_signed(const S& rhs) const& noexcept { const auto r = __private::add_with_overflow_signed(primitive_value, rhs.primitive_value); if (!r.overflow) [[likely]] return r.value; else { if (rhs.primitive_value >= 0) return MAX; else return MIN; } } __attribute__((pure)) inline constexpr u32 unchecked_add( ::sus::marker::UnsafeFnMarker, const u32& rhs) const& noexcept { return u32(__private::unchecked_add(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr u32 wrapping_add(const u32& rhs) const& noexcept { return u32(__private::wrapping_add(primitive_value, rhs.primitive_value)); } template <std::convertible_to<i32> S> __attribute__((pure)) constexpr u32 wrapping_add_signed(const S& rhs) const& noexcept { return __private::add_with_overflow_signed(primitive_value, rhs.primitive_value) .value; } __attribute__((pure)) constexpr ::sus::option::Option<u32> checked_div( const u32& rhs) const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u32, bool> overflowing_div( const u32& rhs) const& noexcept; __attribute__((pure)) constexpr u32 saturating_div(const u32& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return u32(__private::unchecked_div(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr u32 wrapping_div(const u32& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return u32(__private::unchecked_div(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr ::sus::option::Option<u32> checked_mul( const u32& rhs) const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u32, bool> overflowing_mul( const u32& rhs) const& noexcept; __attribute__((pure)) constexpr u32 saturating_mul(const u32& rhs) const& noexcept { return u32(__private::saturating_mul(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr u32 unchecked_mul(::sus::marker::UnsafeFnMarker, const u32& rhs) const& noexcept { return u32(__private::unchecked_mul(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr u32 wrapping_mul(const u32& rhs) const& noexcept { return u32(__private::wrapping_mul(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr ::sus::option::Option<u32> checked_neg() const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u32, bool> overflowing_neg() const& noexcept; __attribute__((pure)) constexpr u32 wrapping_neg() const& noexcept { return (u32(uint32_t{0u})).wrapping_sub(*this); } __attribute__((pure)) constexpr ::sus::option::Option<u32> checked_rem( const u32& rhs) const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u32, bool> overflowing_rem( const u32& rhs) const& noexcept; __attribute__((pure)) constexpr u32 wrapping_rem(const u32& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return u32(__private::unchecked_rem(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr u32 div_euclid(const u32& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return u32(__private::unchecked_div(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr ::sus::option::Option<u32> checked_div_euclid( const u32& rhs) const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u32, bool> overflowing_div_euclid( const u32& rhs) const& noexcept; __attribute__((pure)) constexpr u32 wrapping_div_euclid(const u32& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return u32(__private::unchecked_div(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr u32 rem_euclid(const u32& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return u32(__private::unchecked_rem(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr ::sus::option::Option<u32> checked_rem_euclid( const u32& rhs) const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u32, bool> overflowing_rem_euclid( const u32& rhs) const& noexcept; __attribute__((pure)) constexpr u32 wrapping_rem_euclid(const u32& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return u32(__private::unchecked_rem(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr ::sus::option::Option<u32> checked_shl( const u32& rhs) const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u32, bool> overflowing_shl( const u32& rhs) const& noexcept; __attribute__((pure)) constexpr u32 wrapping_shl(const u32& rhs) const& noexcept { return u32( __private::shl_with_overflow(primitive_value, rhs.primitive_value).value); } __attribute__((pure)) constexpr ::sus::option::Option<u32> checked_shr( const u32& rhs) const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u32, bool> overflowing_shr( const u32& rhs) const& noexcept; __attribute__((pure)) constexpr u32 wrapping_shr(const u32& rhs) const& noexcept { return u32( __private::shr_with_overflow(primitive_value, rhs.primitive_value).value); } __attribute__((pure)) constexpr ::sus::option::Option<u32> checked_sub( const u32& rhs) const&; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u32, bool> overflowing_sub( const u32& rhs) const& noexcept; __attribute__((pure)) constexpr u32 saturating_sub(const u32& rhs) const& { return u32(__private::saturating_sub(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr u32 unchecked_sub(::sus::marker::UnsafeFnMarker, const u32& rhs) const& noexcept { return u32(__private::unchecked_sub(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr u32 wrapping_sub(const u32& rhs) const& noexcept { return u32(__private::wrapping_sub(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr u32 count_ones() const& noexcept { return __private::count_ones(primitive_value); } __attribute__((pure)) constexpr u32 count_zeros() const& noexcept { return (~(*this)).count_ones(); } __attribute__((pure)) constexpr u32 leading_ones() const& noexcept { return (~(*this)).leading_zeros(); } __attribute__((pure)) constexpr u32 leading_zeros() const& noexcept { return __private::leading_zeros(primitive_value); } __attribute__((pure)) constexpr u32 trailing_ones() const& noexcept { return (~(*this)).trailing_zeros(); } __attribute__((pure)) constexpr u32 trailing_zeros() const& noexcept { return __private::trailing_zeros(primitive_value); } __attribute__((pure)) constexpr u32 reverse_bits() const& noexcept { return u32(__private::reverse_bits(primitive_value)); } __attribute__((pure)) constexpr u32 rotate_left(const u32& n) const& noexcept { return u32(__private::rotate_left(primitive_value, n.primitive_value)); } __attribute__((pure)) constexpr u32 rotate_right(const u32& n) const& noexcept { return u32(__private::rotate_right(primitive_value, n.primitive_value)); } __attribute__((pure)) constexpr u32 swap_bytes() const& noexcept { return u32(__private::swap_bytes(primitive_value)); } __attribute__((pure)) constexpr u32 pow(const u32& rhs) const& noexcept { const auto out = __private::pow_with_overflow(primitive_value, rhs.primitive_value); ::sus::check(!out.overflow); return u32(out.value); } __attribute__((pure)) constexpr ::sus::option::Option<u32> checked_pow( const u32& rhs) const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u32, bool> overflowing_pow( const u32& exp) const& noexcept; __attribute__((pure)) constexpr u32 wrapping_pow(const u32& exp) const& noexcept { return u32(__private::wrapping_pow(primitive_value, exp.primitive_value)); } __attribute__((pure)) constexpr ::sus::option::Option<u32> checked_log2() const& noexcept; __attribute__((pure)) constexpr u32 log2() const& noexcept; __attribute__((pure)) constexpr ::sus::option::Option<u32> checked_log10() const& noexcept; __attribute__((pure)) constexpr u32 log10() const& noexcept; __attribute__((pure)) constexpr ::sus::option::Option<u32> checked_log( const u32& base) const& noexcept; __attribute__((pure)) constexpr u32 log(const u32& base) const& noexcept; __attribute__((pure)) constexpr bool is_power_of_two() const& noexcept { return count_ones() == u32(uint32_t{1u}); } __attribute__((pure)) constexpr u32 next_power_of_two() const& noexcept { const auto one_less = __private::one_less_than_next_power_of_two(primitive_value); return u32(one_less) + u32(uint32_t{1u}); } __attribute__((pure)) constexpr ::sus::option::Option<u32> checked_next_power_of_two() const& noexcept; __attribute__((pure)) constexpr u32 wrapping_next_power_of_two() const& noexcept { const auto one_less = __private::one_less_than_next_power_of_two(primitive_value); return u32(one_less).wrapping_add(u32(uint32_t{1u})); } [[nodiscard]] __attribute__((pure)) static constexpr u32 from_be(const u32& x) noexcept { if constexpr (::sus::assertions::is_big_endian()) return x; else return x.swap_bytes(); } [[nodiscard]] __attribute__((pure)) static constexpr u32 from_le(const u32& x) noexcept { if constexpr (::sus::assertions::is_little_endian()) return x; else return x.swap_bytes(); } __attribute__((pure)) constexpr u32 to_be() const& noexcept { if constexpr (::sus::assertions::is_big_endian()) return *this; else return swap_bytes(); } __attribute__((pure)) constexpr u32 to_le() const& noexcept { if constexpr (::sus::assertions::is_little_endian()) return *this; else return swap_bytes(); } __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<uint32_t>()> to_be_bytes() const& noexcept; __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<uint32_t>()> to_le_bytes() const& noexcept; __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<uint32_t>()> to_ne_bytes() const& noexcept; [[nodiscard]] __attribute__((pure)) static constexpr u32 from_be_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<uint32_t>()>& bytes) noexcept; [[nodiscard]] __attribute__((pure)) static constexpr u32 from_le_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<uint32_t>()>& bytes) noexcept; [[nodiscard]] __attribute__((pure)) static constexpr u32 from_ne_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<uint32_t>()>& bytes) noexcept; }; inline constexpr u32 u32::MIN = u32(u32::MIN_PRIMITIVE); inline constexpr u32 u32::MAX = u32(u32::MAX_PRIMITIVE); inline constexpr u32 u32::BITS = u32(__private::num_bits<uint32_t>()); struct u8 final { uint8_t primitive_value{0u}; static constexpr auto MIN_PRIMITIVE = __private::min_value<uint8_t>(); static constexpr auto MAX_PRIMITIVE = __private::max_value<uint8_t>(); static const u8 MIN; static const u8 MAX; static const u32 BITS; constexpr inline u8() noexcept = default; template <Unsigned U> requires(::sus::mem::size_of<U>() <= ::sus::mem::size_of<uint8_t>()) constexpr inline u8(U v) noexcept : primitive_value(v.primitive_value) {} template <UnsignedPrimitiveInteger P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of<uint8_t>()) constexpr inline u8(P v) noexcept : primitive_value(v) {} template <UnsignedPrimitiveEnum P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of<uint8_t>()) constexpr inline u8(P v) noexcept : primitive_value(v) {} template <UnsignedPrimitiveEnumClass P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of<uint8_t>()) explicit constexpr inline u8(P v) noexcept : primitive_value(static_cast<uint8_t>(v)) {} template <Unsigned U> requires(::sus::mem::size_of<U>() <= ::sus::mem::size_of<uint8_t>()) constexpr inline u8& operator=(U v) noexcept { primitive_value = v.primitive_value; return *this; } template <UnsignedPrimitiveInteger P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of<uint8_t>()) constexpr inline u8& operator=(P v) noexcept { primitive_value = v; return *this; } template <UnsignedPrimitiveEnum P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of<uint8_t>()) constexpr inline u8& operator=(P v) noexcept { primitive_value = static_cast<uint8_t>(v); return *this; } template <Unsigned U> requires(::sus::mem::size_of<U>() <= ::sus::mem::size_of<uint8_t>()) __attribute__((pure)) static constexpr u8 from(U u) noexcept { return u8(static_cast<uint8_t>(u.primitive_value)); } template <Unsigned U> __attribute__((pure)) static constexpr ::sus::result::Result<u8, ::sus::num::TryFromIntError> try_from(U u) noexcept; template <UnsignedPrimitiveInteger U> requires(::sus::mem::size_of<U>() <= ::sus::mem::size_of<uint8_t>()) __attribute__((pure)) static constexpr u8 from(U u) noexcept { return u8(static_cast<uint8_t>(u)); } template <UnsignedPrimitiveInteger U> __attribute__((pure)) static constexpr ::sus::result::Result<u8, ::sus::num::TryFromIntError> try_from(U u) noexcept; template <Signed S> __attribute__((pure)) static constexpr ::sus::result::Result<u8, ::sus::num::TryFromIntError> try_from(S s) noexcept; template <SignedPrimitiveInteger S> __attribute__((pure)) static constexpr ::sus::result::Result<u8, ::sus::num::TryFromIntError> try_from(S s) noexcept; template <class S> requires(SignedPrimitiveEnum<S> || SignedPrimitiveEnumClass<S>) __attribute__((pure)) static constexpr ::sus::result::Result<u8, ::sus::num::TryFromIntError> try_from(S s) noexcept; template <class U> requires((UnsignedPrimitiveEnum<U> || UnsignedPrimitiveEnumClass<U>) && ::sus::mem::size_of<U>() <= ::sus::mem::size_of<uint8_t>()) __attribute__((pure)) static constexpr u8 from(U u) noexcept { return u8(static_cast<std::underlying_type_t<U>>(u)); } template <class U> requires(UnsignedPrimitiveEnum<U> || UnsignedPrimitiveEnumClass<U>) __attribute__((pure)) static constexpr ::sus::result::Result<u8, ::sus::num::TryFromIntError> try_from(U u) noexcept; static constexpr u8 from_product( ::sus::iter::Iterator<u8> auto&& it) noexcept { auto p = u8(uint8_t{1u}); for (u8 i : ::sus::move(it)) p *= i; return p; } static constexpr u8 from_sum( ::sus::iter::Iterator<u8> auto&& it) noexcept { auto p = u8(uint8_t{0u}); for (u8 i : ::sus::move(it)) p += i; return p; } template <UnsignedPrimitiveInteger U> requires(::sus::mem::size_of<U>() >= ::sus::mem::size_of<uint8_t>()) __attribute__((pure)) constexpr inline explicit operator U() const { return primitive_value; } [[nodiscard]] __attribute__((pure)) friend constexpr inline bool operator==( const u8& l, const u8& r) noexcept = default; template <UnsignedPrimitiveInteger P> [[nodiscard]] __attribute__((pure)) friend constexpr inline bool operator==( const u8& l, const P& r) noexcept { return l.primitive_value == r; } template <Unsigned U> [[nodiscard]] __attribute__((pure)) friend constexpr inline bool operator==( const u8& l, const U& r) noexcept { return l.primitive_value == r.primitive_value; } template <UnsignedPrimitiveInteger P> [[nodiscard]] __attribute__((pure)) friend constexpr inline std::strong_ordering operator<=>( const u8& l, const u8& r) noexcept { return l.primitive_value <=> r.primitive_value; } template <UnsignedPrimitiveInteger P> [[nodiscard]] __attribute__((pure)) friend constexpr inline std::strong_ordering operator<=>( const u8& l, const P& r) noexcept { return l.primitive_value <=> r; } template <Unsigned U> [[nodiscard]] __attribute__((pure)) friend constexpr inline std::strong_ordering operator<=>( const u8& l, const U& r) noexcept { return l.primitive_value <=> r.primitive_value; } __attribute__((pure)) constexpr inline u8 operator~() const& noexcept { return u8(__private::unchecked_not(primitive_value)); } [[nodiscard]] __attribute__((pure)) friend constexpr inline u8 operator+( const u8& l, const u8& r) noexcept { const auto out = __private::add_with_overflow(l.primitive_value, r.primitive_value); ::sus::check(!out.overflow); return u8(out.value); } [[nodiscard]] __attribute__((pure)) friend constexpr inline u8 operator-( const u8& l, const u8& r) noexcept { const auto out = __private::sub_with_overflow(l.primitive_value, r.primitive_value); ::sus::check(!out.overflow); return u8(out.value); } [[nodiscard]] __attribute__((pure)) friend constexpr inline u8 operator*( const u8& l, const u8& r) noexcept { const auto out = __private::mul_with_overflow(l.primitive_value, r.primitive_value); ::sus::check(!out.overflow); return u8(out.value); } [[nodiscard]] __attribute__((pure)) friend constexpr inline u8 operator/( const u8& l, const u8& r) noexcept { ::sus::check(r.primitive_value != 0u); return u8(__private::unchecked_div(l.primitive_value, r.primitive_value)); } [[nodiscard]] __attribute__((pure)) friend constexpr inline u8 operator%( const u8& l, const u8& r) noexcept { ::sus::check(r.primitive_value != 0u); return u8(__private::unchecked_rem(l.primitive_value, r.primitive_value)); } [[nodiscard]] __attribute__((pure)) friend constexpr inline u8 operator&( const u8& l, const u8& r) noexcept { return u8(__private::unchecked_and(l.primitive_value, r.primitive_value)); } [[nodiscard]] __attribute__((pure)) friend constexpr inline u8 operator|( const u8& l, const u8& r) noexcept { return u8(__private::unchecked_or(l.primitive_value, r.primitive_value)); } [[nodiscard]] __attribute__((pure)) friend constexpr inline u8 operator^( const u8& l, const u8& r) noexcept { return u8(__private::unchecked_xor(l.primitive_value, r.primitive_value)); } [[nodiscard]] __attribute__((pure)) friend constexpr inline u8 operator<<( const u8& l, const u32& r) noexcept { ::sus::check(r < BITS); return u8(__private::unchecked_shl(l.primitive_value, r.primitive_value)); } [[nodiscard]] __attribute__((pure)) friend constexpr inline u8 operator>>( const u8& l, const u32& r) noexcept { ::sus::check(r < BITS); return u8(__private::unchecked_shr(l.primitive_value, r.primitive_value)); } constexpr inline void operator+=(u8 r) & noexcept { const auto out = __private::add_with_overflow(primitive_value, r.primitive_value); ::sus::check(!out.overflow); primitive_value = out.value; } constexpr inline void operator-=(u8 r) & noexcept { const auto out = __private::sub_with_overflow(primitive_value, r.primitive_value); ::sus::check(!out.overflow); primitive_value = out.value; } constexpr inline void operator*=(u8 r) & noexcept { const auto out = __private::mul_with_overflow(primitive_value, r.primitive_value); ::sus::check(!out.overflow); primitive_value = out.value; } constexpr inline void operator/=(u8 r) & noexcept { ::sus::check(r.primitive_value != 0u); primitive_value /= r.primitive_value; } constexpr inline void operator%=(u8 r) & noexcept { ::sus::check(r.primitive_value != 0u); primitive_value %= r.primitive_value; } constexpr inline void operator&=(u8 r) & noexcept { primitive_value &= r.primitive_value; } constexpr inline void operator|=(u8 r) & noexcept { primitive_value |= r.primitive_value; } constexpr inline void operator^=(u8 r) & noexcept { primitive_value ^= r.primitive_value; } constexpr inline void operator<<=(const u32& r) & noexcept { ::sus::check(r < BITS); primitive_value <<= r.primitive_value; } constexpr inline void operator>>=(const u32& r) & noexcept { ::sus::check(r < BITS); primitive_value >>= r.primitive_value; } __attribute__((pure)) constexpr u8 abs_diff(const u8& r) const& noexcept { if (primitive_value >= r.primitive_value) return u8(__private::unchecked_sub(primitive_value, r.primitive_value)); else return u8(__private::unchecked_sub(r.primitive_value, primitive_value)); } __attribute__((pure)) constexpr ::sus::option::Option<u8> checked_add( const u8& rhs) const& noexcept; template <std::convertible_to<i8> S> __attribute__((pure)) constexpr ::sus::option::Option<u8> checked_add_signed( const S& rhs) const& noexcept; __attribute__((pure)) constexpr sus::tuple_type::Tuple<u8, bool> overflowing_add( const u8& rhs) const& noexcept; template <std::convertible_to<i8> S> __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u8, bool> overflowing_add_signed( const S& rhs) const& noexcept; __attribute__((pure)) constexpr u8 saturating_add(const u8& rhs) const& noexcept { return u8(__private::saturating_add(primitive_value, rhs.primitive_value)); } template <std::convertible_to<i8> S> __attribute__((pure)) constexpr u8 saturating_add_signed(const S& rhs) const& noexcept { const auto r = __private::add_with_overflow_signed(primitive_value, rhs.primitive_value); if (!r.overflow) [[likely]] return r.value; else { if (rhs.primitive_value >= 0) return MAX; else return MIN; } } __attribute__((pure)) inline constexpr u8 unchecked_add( ::sus::marker::UnsafeFnMarker, const u8& rhs) const& noexcept { return u8(__private::unchecked_add(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr u8 wrapping_add(const u8& rhs) const& noexcept { return u8(__private::wrapping_add(primitive_value, rhs.primitive_value)); } template <std::convertible_to<i8> S> __attribute__((pure)) constexpr u8 wrapping_add_signed(const S& rhs) const& noexcept { return __private::add_with_overflow_signed(primitive_value, rhs.primitive_value) .value; } __attribute__((pure)) constexpr ::sus::option::Option<u8> checked_div( const u8& rhs) const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u8, bool> overflowing_div( const u8& rhs) const& noexcept; __attribute__((pure)) constexpr u8 saturating_div(const u8& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return u8(__private::unchecked_div(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr u8 wrapping_div(const u8& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return u8(__private::unchecked_div(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr ::sus::option::Option<u8> checked_mul( const u8& rhs) const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u8, bool> overflowing_mul( const u8& rhs) const& noexcept; __attribute__((pure)) constexpr u8 saturating_mul(const u8& rhs) const& noexcept { return u8(__private::saturating_mul(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr u8 unchecked_mul(::sus::marker::UnsafeFnMarker, const u8& rhs) const& noexcept { return u8(__private::unchecked_mul(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr u8 wrapping_mul(const u8& rhs) const& noexcept { return u8(__private::wrapping_mul(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr ::sus::option::Option<u8> checked_neg() const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u8, bool> overflowing_neg() const& noexcept; __attribute__((pure)) constexpr u8 wrapping_neg() const& noexcept { return (u8(uint8_t{0u})).wrapping_sub(*this); } __attribute__((pure)) constexpr ::sus::option::Option<u8> checked_rem( const u8& rhs) const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u8, bool> overflowing_rem( const u8& rhs) const& noexcept; __attribute__((pure)) constexpr u8 wrapping_rem(const u8& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return u8(__private::unchecked_rem(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr u8 div_euclid(const u8& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return u8(__private::unchecked_div(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr ::sus::option::Option<u8> checked_div_euclid( const u8& rhs) const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u8, bool> overflowing_div_euclid( const u8& rhs) const& noexcept; __attribute__((pure)) constexpr u8 wrapping_div_euclid(const u8& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return u8(__private::unchecked_div(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr u8 rem_euclid(const u8& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return u8(__private::unchecked_rem(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr ::sus::option::Option<u8> checked_rem_euclid( const u8& rhs) const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u8, bool> overflowing_rem_euclid( const u8& rhs) const& noexcept; __attribute__((pure)) constexpr u8 wrapping_rem_euclid(const u8& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return u8(__private::unchecked_rem(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr ::sus::option::Option<u8> checked_shl( const u32& rhs) const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u8, bool> overflowing_shl( const u32& rhs) const& noexcept; __attribute__((pure)) constexpr u8 wrapping_shl(const u32& rhs) const& noexcept { return u8( __private::shl_with_overflow(primitive_value, rhs.primitive_value).value); } __attribute__((pure)) constexpr ::sus::option::Option<u8> checked_shr( const u32& rhs) const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u8, bool> overflowing_shr( const u32& rhs) const& noexcept; __attribute__((pure)) constexpr u8 wrapping_shr(const u32& rhs) const& noexcept { return u8( __private::shr_with_overflow(primitive_value, rhs.primitive_value).value); } __attribute__((pure)) constexpr ::sus::option::Option<u8> checked_sub( const u8& rhs) const&; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u8, bool> overflowing_sub( const u8& rhs) const& noexcept; __attribute__((pure)) constexpr u8 saturating_sub(const u8& rhs) const& { return u8(__private::saturating_sub(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr u8 unchecked_sub(::sus::marker::UnsafeFnMarker, const u8& rhs) const& noexcept { return u8(__private::unchecked_sub(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr u8 wrapping_sub(const u8& rhs) const& noexcept { return u8(__private::wrapping_sub(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr u32 count_ones() const& noexcept { return __private::count_ones(primitive_value); } __attribute__((pure)) constexpr u32 count_zeros() const& noexcept { return (~(*this)).count_ones(); } __attribute__((pure)) constexpr u32 leading_ones() const& noexcept { return (~(*this)).leading_zeros(); } __attribute__((pure)) constexpr u32 leading_zeros() const& noexcept { return __private::leading_zeros(primitive_value); } __attribute__((pure)) constexpr u32 trailing_ones() const& noexcept { return (~(*this)).trailing_zeros(); } __attribute__((pure)) constexpr u32 trailing_zeros() const& noexcept { return __private::trailing_zeros(primitive_value); } __attribute__((pure)) constexpr u8 reverse_bits() const& noexcept { return u8(__private::reverse_bits(primitive_value)); } __attribute__((pure)) constexpr u8 rotate_left(const u32& n) const& noexcept { return u8(__private::rotate_left(primitive_value, n.primitive_value)); } __attribute__((pure)) constexpr u8 rotate_right(const u32& n) const& noexcept { return u8(__private::rotate_right(primitive_value, n.primitive_value)); } __attribute__((pure)) constexpr u8 swap_bytes() const& noexcept { return u8(__private::swap_bytes(primitive_value)); } __attribute__((pure)) constexpr u8 pow(const u32& rhs) const& noexcept { const auto out = __private::pow_with_overflow(primitive_value, rhs.primitive_value); ::sus::check(!out.overflow); return u8(out.value); } __attribute__((pure)) constexpr ::sus::option::Option<u8> checked_pow( const u32& rhs) const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u8, bool> overflowing_pow( const u32& exp) const& noexcept; __attribute__((pure)) constexpr u8 wrapping_pow(const u32& exp) const& noexcept { return u8(__private::wrapping_pow(primitive_value, exp.primitive_value)); } __attribute__((pure)) constexpr ::sus::option::Option<u32> checked_log2() const& noexcept; __attribute__((pure)) constexpr u32 log2() const& noexcept; __attribute__((pure)) constexpr ::sus::option::Option<u32> checked_log10() const& noexcept; __attribute__((pure)) constexpr u32 log10() const& noexcept; __attribute__((pure)) constexpr ::sus::option::Option<u32> checked_log( const u8& base) const& noexcept; __attribute__((pure)) constexpr u32 log(const u8& base) const& noexcept; __attribute__((pure)) constexpr bool is_power_of_two() const& noexcept { return count_ones() == u8(uint8_t{1u}); } __attribute__((pure)) constexpr u8 next_power_of_two() const& noexcept { const auto one_less = __private::one_less_than_next_power_of_two(primitive_value); return u8(one_less) + u8(uint8_t{1u}); } __attribute__((pure)) constexpr ::sus::option::Option<u8> checked_next_power_of_two() const& noexcept; __attribute__((pure)) constexpr u8 wrapping_next_power_of_two() const& noexcept { const auto one_less = __private::one_less_than_next_power_of_two(primitive_value); return u8(one_less).wrapping_add(u8(uint8_t{1u})); } [[nodiscard]] __attribute__((pure)) static constexpr u8 from_be(const u8& x) noexcept { if constexpr (::sus::assertions::is_big_endian()) return x; else return x.swap_bytes(); } [[nodiscard]] __attribute__((pure)) static constexpr u8 from_le(const u8& x) noexcept { if constexpr (::sus::assertions::is_little_endian()) return x; else return x.swap_bytes(); } __attribute__((pure)) constexpr u8 to_be() const& noexcept { if constexpr (::sus::assertions::is_big_endian()) return *this; else return swap_bytes(); } __attribute__((pure)) constexpr u8 to_le() const& noexcept { if constexpr (::sus::assertions::is_little_endian()) return *this; else return swap_bytes(); } __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<uint8_t>()> to_be_bytes() const& noexcept; __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<uint8_t>()> to_le_bytes() const& noexcept; __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<uint8_t>()> to_ne_bytes() const& noexcept; [[nodiscard]] __attribute__((pure)) static constexpr u8 from_be_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<uint8_t>()>& bytes) noexcept; [[nodiscard]] __attribute__((pure)) static constexpr u8 from_le_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<uint8_t>()>& bytes) noexcept; [[nodiscard]] __attribute__((pure)) static constexpr u8 from_ne_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<uint8_t>()>& bytes) noexcept; }; inline constexpr u8 u8::MIN = u8(u8::MIN_PRIMITIVE); inline constexpr u8 u8::MAX = u8(u8::MAX_PRIMITIVE); inline constexpr u32 u8::BITS = u32(__private::num_bits<uint8_t>()); struct u16 final { uint16_t primitive_value{0u}; static constexpr auto MIN_PRIMITIVE = __private::min_value<uint16_t>(); static constexpr auto MAX_PRIMITIVE = __private::max_value<uint16_t>(); static const u16 MIN; static const u16 MAX; static const u32 BITS; constexpr inline u16() noexcept = default; template <Unsigned U> requires(::sus::mem::size_of<U>() <= ::sus::mem::size_of<uint16_t>()) constexpr inline u16(U v) noexcept : primitive_value(v.primitive_value) {} template <UnsignedPrimitiveInteger P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of<uint16_t>()) constexpr inline u16(P v) noexcept : primitive_value(v) {} template <UnsignedPrimitiveEnum P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of<uint16_t>()) constexpr inline u16(P v) noexcept : primitive_value(v) {} template <UnsignedPrimitiveEnumClass P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of<uint16_t>()) explicit constexpr inline u16(P v) noexcept : primitive_value(static_cast<uint16_t>(v)) {} template <Unsigned U> requires(::sus::mem::size_of<U>() <= ::sus::mem::size_of<uint16_t>()) constexpr inline u16& operator=(U v) noexcept { primitive_value = v.primitive_value; return *this; } template <UnsignedPrimitiveInteger P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of<uint16_t>()) constexpr inline u16& operator=(P v) noexcept { primitive_value = v; return *this; } template <UnsignedPrimitiveEnum P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of<uint16_t>()) constexpr inline u16& operator=(P v) noexcept { primitive_value = static_cast<uint16_t>(v); return *this; } template <Unsigned U> requires(::sus::mem::size_of<U>() <= ::sus::mem::size_of<uint16_t>()) __attribute__((pure)) static constexpr u16 from(U u) noexcept { return u16(static_cast<uint16_t>(u.primitive_value)); } template <Unsigned U> __attribute__((pure)) static constexpr ::sus::result::Result<u16, ::sus::num::TryFromIntError> try_from(U u) noexcept; template <UnsignedPrimitiveInteger U> requires(::sus::mem::size_of<U>() <= ::sus::mem::size_of<uint16_t>()) __attribute__((pure)) static constexpr u16 from(U u) noexcept { return u16(static_cast<uint16_t>(u)); } template <UnsignedPrimitiveInteger U> __attribute__((pure)) static constexpr ::sus::result::Result<u16, ::sus::num::TryFromIntError> try_from(U u) noexcept; template <Signed S> __attribute__((pure)) static constexpr ::sus::result::Result<u16, ::sus::num::TryFromIntError> try_from(S s) noexcept; template <SignedPrimitiveInteger S> __attribute__((pure)) static constexpr ::sus::result::Result<u16, ::sus::num::TryFromIntError> try_from(S s) noexcept; template <class S> requires(SignedPrimitiveEnum<S> || SignedPrimitiveEnumClass<S>) __attribute__((pure)) static constexpr ::sus::result::Result<u16, ::sus::num::TryFromIntError> try_from(S s) noexcept; template <class U> requires((UnsignedPrimitiveEnum<U> || UnsignedPrimitiveEnumClass<U>) && ::sus::mem::size_of<U>() <= ::sus::mem::size_of<uint16_t>()) __attribute__((pure)) static constexpr u16 from(U u) noexcept { return u16(static_cast<std::underlying_type_t<U>>(u)); } template <class U> requires(UnsignedPrimitiveEnum<U> || UnsignedPrimitiveEnumClass<U>) __attribute__((pure)) static constexpr ::sus::result::Result<u16, ::sus::num::TryFromIntError> try_from(U u) noexcept; static constexpr u16 from_product( ::sus::iter::Iterator<u16> auto&& it) noexcept { auto p = u16(uint16_t{1u}); for (u16 i : ::sus::move(it)) p *= i; return p; } static constexpr u16 from_sum( ::sus::iter::Iterator<u16> auto&& it) noexcept { auto p = u16(uint16_t{0u}); for (u16 i : ::sus::move(it)) p += i; return p; } template <UnsignedPrimitiveInteger U> requires(::sus::mem::size_of<U>() >= ::sus::mem::size_of<uint16_t>()) __attribute__((pure)) constexpr inline explicit operator U() const { return primitive_value; } [[nodiscard]] __attribute__((pure)) friend constexpr inline bool operator==( const u16& l, const u16& r) noexcept = default; template <UnsignedPrimitiveInteger P> [[nodiscard]] __attribute__((pure)) friend constexpr inline bool operator==( const u16& l, const P& r) noexcept { return l.primitive_value == r; } template <Unsigned U> [[nodiscard]] __attribute__((pure)) friend constexpr inline bool operator==( const u16& l, const U& r) noexcept { return l.primitive_value == r.primitive_value; } template <UnsignedPrimitiveInteger P> [[nodiscard]] __attribute__((pure)) friend constexpr inline std::strong_ordering operator<=>( const u16& l, const u16& r) noexcept { return l.primitive_value <=> r.primitive_value; } template <UnsignedPrimitiveInteger P> [[nodiscard]] __attribute__((pure)) friend constexpr inline std::strong_ordering operator<=>( const u16& l, const P& r) noexcept { return l.primitive_value <=> r; } template <Unsigned U> [[nodiscard]] __attribute__((pure)) friend constexpr inline std::strong_ordering operator<=>( const u16& l, const U& r) noexcept { return l.primitive_value <=> r.primitive_value; } __attribute__((pure)) constexpr inline u16 operator~() const& noexcept { return u16(__private::unchecked_not(primitive_value)); } [[nodiscard]] __attribute__((pure)) friend constexpr inline u16 operator+( const u16& l, const u16& r) noexcept { const auto out = __private::add_with_overflow(l.primitive_value, r.primitive_value); ::sus::check(!out.overflow); return u16(out.value); } [[nodiscard]] __attribute__((pure)) friend constexpr inline u16 operator-( const u16& l, const u16& r) noexcept { const auto out = __private::sub_with_overflow(l.primitive_value, r.primitive_value); ::sus::check(!out.overflow); return u16(out.value); } [[nodiscard]] __attribute__((pure)) friend constexpr inline u16 operator*( const u16& l, const u16& r) noexcept { const auto out = __private::mul_with_overflow(l.primitive_value, r.primitive_value); ::sus::check(!out.overflow); return u16(out.value); } [[nodiscard]] __attribute__((pure)) friend constexpr inline u16 operator/( const u16& l, const u16& r) noexcept { ::sus::check(r.primitive_value != 0u); return u16(__private::unchecked_div(l.primitive_value, r.primitive_value)); } [[nodiscard]] __attribute__((pure)) friend constexpr inline u16 operator%( const u16& l, const u16& r) noexcept { ::sus::check(r.primitive_value != 0u); return u16(__private::unchecked_rem(l.primitive_value, r.primitive_value)); } [[nodiscard]] __attribute__((pure)) friend constexpr inline u16 operator&( const u16& l, const u16& r) noexcept { return u16(__private::unchecked_and(l.primitive_value, r.primitive_value)); } [[nodiscard]] __attribute__((pure)) friend constexpr inline u16 operator|( const u16& l, const u16& r) noexcept { return u16(__private::unchecked_or(l.primitive_value, r.primitive_value)); } [[nodiscard]] __attribute__((pure)) friend constexpr inline u16 operator^( const u16& l, const u16& r) noexcept { return u16(__private::unchecked_xor(l.primitive_value, r.primitive_value)); } [[nodiscard]] __attribute__((pure)) friend constexpr inline u16 operator<<( const u16& l, const u32& r) noexcept { ::sus::check(r < BITS); return u16(__private::unchecked_shl(l.primitive_value, r.primitive_value)); } [[nodiscard]] __attribute__((pure)) friend constexpr inline u16 operator>>( const u16& l, const u32& r) noexcept { ::sus::check(r < BITS); return u16(__private::unchecked_shr(l.primitive_value, r.primitive_value)); } constexpr inline void operator+=(u16 r) & noexcept { const auto out = __private::add_with_overflow(primitive_value, r.primitive_value); ::sus::check(!out.overflow); primitive_value = out.value; } constexpr inline void operator-=(u16 r) & noexcept { const auto out = __private::sub_with_overflow(primitive_value, r.primitive_value); ::sus::check(!out.overflow); primitive_value = out.value; } constexpr inline void operator*=(u16 r) & noexcept { const auto out = __private::mul_with_overflow(primitive_value, r.primitive_value); ::sus::check(!out.overflow); primitive_value = out.value; } constexpr inline void operator/=(u16 r) & noexcept { ::sus::check(r.primitive_value != 0u); primitive_value /= r.primitive_value; } constexpr inline void operator%=(u16 r) & noexcept { ::sus::check(r.primitive_value != 0u); primitive_value %= r.primitive_value; } constexpr inline void operator&=(u16 r) & noexcept { primitive_value &= r.primitive_value; } constexpr inline void operator|=(u16 r) & noexcept { primitive_value |= r.primitive_value; } constexpr inline void operator^=(u16 r) & noexcept { primitive_value ^= r.primitive_value; } constexpr inline void operator<<=(const u32& r) & noexcept { ::sus::check(r < BITS); primitive_value <<= r.primitive_value; } constexpr inline void operator>>=(const u32& r) & noexcept { ::sus::check(r < BITS); primitive_value >>= r.primitive_value; } __attribute__((pure)) constexpr u16 abs_diff(const u16& r) const& noexcept { if (primitive_value >= r.primitive_value) return u16(__private::unchecked_sub(primitive_value, r.primitive_value)); else return u16(__private::unchecked_sub(r.primitive_value, primitive_value)); } __attribute__((pure)) constexpr ::sus::option::Option<u16> checked_add( const u16& rhs) const& noexcept; template <std::convertible_to<i16> S> __attribute__((pure)) constexpr ::sus::option::Option<u16> checked_add_signed( const S& rhs) const& noexcept; __attribute__((pure)) constexpr sus::tuple_type::Tuple<u16, bool> overflowing_add( const u16& rhs) const& noexcept; template <std::convertible_to<i16> S> __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u16, bool> overflowing_add_signed( const S& rhs) const& noexcept; __attribute__((pure)) constexpr u16 saturating_add(const u16& rhs) const& noexcept { return u16(__private::saturating_add(primitive_value, rhs.primitive_value)); } template <std::convertible_to<i16> S> __attribute__((pure)) constexpr u16 saturating_add_signed(const S& rhs) const& noexcept { const auto r = __private::add_with_overflow_signed(primitive_value, rhs.primitive_value); if (!r.overflow) [[likely]] return r.value; else { if (rhs.primitive_value >= 0) return MAX; else return MIN; } } __attribute__((pure)) inline constexpr u16 unchecked_add( ::sus::marker::UnsafeFnMarker, const u16& rhs) const& noexcept { return u16(__private::unchecked_add(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr u16 wrapping_add(const u16& rhs) const& noexcept { return u16(__private::wrapping_add(primitive_value, rhs.primitive_value)); } template <std::convertible_to<i16> S> __attribute__((pure)) constexpr u16 wrapping_add_signed(const S& rhs) const& noexcept { return __private::add_with_overflow_signed(primitive_value, rhs.primitive_value) .value; } __attribute__((pure)) constexpr ::sus::option::Option<u16> checked_div( const u16& rhs) const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u16, bool> overflowing_div( const u16& rhs) const& noexcept; __attribute__((pure)) constexpr u16 saturating_div(const u16& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return u16(__private::unchecked_div(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr u16 wrapping_div(const u16& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return u16(__private::unchecked_div(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr ::sus::option::Option<u16> checked_mul( const u16& rhs) const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u16, bool> overflowing_mul( const u16& rhs) const& noexcept; __attribute__((pure)) constexpr u16 saturating_mul(const u16& rhs) const& noexcept { return u16(__private::saturating_mul(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr u16 unchecked_mul(::sus::marker::UnsafeFnMarker, const u16& rhs) const& noexcept { return u16(__private::unchecked_mul(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr u16 wrapping_mul(const u16& rhs) const& noexcept { return u16(__private::wrapping_mul(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr ::sus::option::Option<u16> checked_neg() const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u16, bool> overflowing_neg() const& noexcept; __attribute__((pure)) constexpr u16 wrapping_neg() const& noexcept { return (u16(uint16_t{0u})).wrapping_sub(*this); } __attribute__((pure)) constexpr ::sus::option::Option<u16> checked_rem( const u16& rhs) const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u16, bool> overflowing_rem( const u16& rhs) const& noexcept; __attribute__((pure)) constexpr u16 wrapping_rem(const u16& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return u16(__private::unchecked_rem(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr u16 div_euclid(const u16& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return u16(__private::unchecked_div(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr ::sus::option::Option<u16> checked_div_euclid( const u16& rhs) const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u16, bool> overflowing_div_euclid( const u16& rhs) const& noexcept; __attribute__((pure)) constexpr u16 wrapping_div_euclid(const u16& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return u16(__private::unchecked_div(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr u16 rem_euclid(const u16& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return u16(__private::unchecked_rem(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr ::sus::option::Option<u16> checked_rem_euclid( const u16& rhs) const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u16, bool> overflowing_rem_euclid( const u16& rhs) const& noexcept; __attribute__((pure)) constexpr u16 wrapping_rem_euclid(const u16& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return u16(__private::unchecked_rem(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr ::sus::option::Option<u16> checked_shl( const u32& rhs) const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u16, bool> overflowing_shl( const u32& rhs) const& noexcept; __attribute__((pure)) constexpr u16 wrapping_shl(const u32& rhs) const& noexcept { return u16( __private::shl_with_overflow(primitive_value, rhs.primitive_value).value); } __attribute__((pure)) constexpr ::sus::option::Option<u16> checked_shr( const u32& rhs) const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u16, bool> overflowing_shr( const u32& rhs) const& noexcept; __attribute__((pure)) constexpr u16 wrapping_shr(const u32& rhs) const& noexcept { return u16( __private::shr_with_overflow(primitive_value, rhs.primitive_value).value); } __attribute__((pure)) constexpr ::sus::option::Option<u16> checked_sub( const u16& rhs) const&; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u16, bool> overflowing_sub( const u16& rhs) const& noexcept; __attribute__((pure)) constexpr u16 saturating_sub(const u16& rhs) const& { return u16(__private::saturating_sub(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr u16 unchecked_sub(::sus::marker::UnsafeFnMarker, const u16& rhs) const& noexcept { return u16(__private::unchecked_sub(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr u16 wrapping_sub(const u16& rhs) const& noexcept { return u16(__private::wrapping_sub(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr u32 count_ones() const& noexcept { return __private::count_ones(primitive_value); } __attribute__((pure)) constexpr u32 count_zeros() const& noexcept { return (~(*this)).count_ones(); } __attribute__((pure)) constexpr u32 leading_ones() const& noexcept { return (~(*this)).leading_zeros(); } __attribute__((pure)) constexpr u32 leading_zeros() const& noexcept { return __private::leading_zeros(primitive_value); } __attribute__((pure)) constexpr u32 trailing_ones() const& noexcept { return (~(*this)).trailing_zeros(); } __attribute__((pure)) constexpr u32 trailing_zeros() const& noexcept { return __private::trailing_zeros(primitive_value); } __attribute__((pure)) constexpr u16 reverse_bits() const& noexcept { return u16(__private::reverse_bits(primitive_value)); } __attribute__((pure)) constexpr u16 rotate_left(const u32& n) const& noexcept { return u16(__private::rotate_left(primitive_value, n.primitive_value)); } __attribute__((pure)) constexpr u16 rotate_right(const u32& n) const& noexcept { return u16(__private::rotate_right(primitive_value, n.primitive_value)); } __attribute__((pure)) constexpr u16 swap_bytes() const& noexcept { return u16(__private::swap_bytes(primitive_value)); } __attribute__((pure)) constexpr u16 pow(const u32& rhs) const& noexcept { const auto out = __private::pow_with_overflow(primitive_value, rhs.primitive_value); ::sus::check(!out.overflow); return u16(out.value); } __attribute__((pure)) constexpr ::sus::option::Option<u16> checked_pow( const u32& rhs) const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u16, bool> overflowing_pow( const u32& exp) const& noexcept; __attribute__((pure)) constexpr u16 wrapping_pow(const u32& exp) const& noexcept { return u16(__private::wrapping_pow(primitive_value, exp.primitive_value)); } __attribute__((pure)) constexpr ::sus::option::Option<u32> checked_log2() const& noexcept; __attribute__((pure)) constexpr u32 log2() const& noexcept; __attribute__((pure)) constexpr ::sus::option::Option<u32> checked_log10() const& noexcept; __attribute__((pure)) constexpr u32 log10() const& noexcept; __attribute__((pure)) constexpr ::sus::option::Option<u32> checked_log( const u16& base) const& noexcept; __attribute__((pure)) constexpr u32 log(const u16& base) const& noexcept; __attribute__((pure)) constexpr bool is_power_of_two() const& noexcept { return count_ones() == u16(uint16_t{1u}); } __attribute__((pure)) constexpr u16 next_power_of_two() const& noexcept { const auto one_less = __private::one_less_than_next_power_of_two(primitive_value); return u16(one_less) + u16(uint16_t{1u}); } __attribute__((pure)) constexpr ::sus::option::Option<u16> checked_next_power_of_two() const& noexcept; __attribute__((pure)) constexpr u16 wrapping_next_power_of_two() const& noexcept { const auto one_less = __private::one_less_than_next_power_of_two(primitive_value); return u16(one_less).wrapping_add(u16(uint16_t{1u})); } [[nodiscard]] __attribute__((pure)) static constexpr u16 from_be(const u16& x) noexcept { if constexpr (::sus::assertions::is_big_endian()) return x; else return x.swap_bytes(); } [[nodiscard]] __attribute__((pure)) static constexpr u16 from_le(const u16& x) noexcept { if constexpr (::sus::assertions::is_little_endian()) return x; else return x.swap_bytes(); } __attribute__((pure)) constexpr u16 to_be() const& noexcept { if constexpr (::sus::assertions::is_big_endian()) return *this; else return swap_bytes(); } __attribute__((pure)) constexpr u16 to_le() const& noexcept { if constexpr (::sus::assertions::is_little_endian()) return *this; else return swap_bytes(); } __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<uint16_t>()> to_be_bytes() const& noexcept; __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<uint16_t>()> to_le_bytes() const& noexcept; __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<uint16_t>()> to_ne_bytes() const& noexcept; [[nodiscard]] __attribute__((pure)) static constexpr u16 from_be_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<uint16_t>()>& bytes) noexcept; [[nodiscard]] __attribute__((pure)) static constexpr u16 from_le_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<uint16_t>()>& bytes) noexcept; [[nodiscard]] __attribute__((pure)) static constexpr u16 from_ne_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<uint16_t>()>& bytes) noexcept; }; inline constexpr u16 u16::MIN = u16(u16::MIN_PRIMITIVE); inline constexpr u16 u16::MAX = u16(u16::MAX_PRIMITIVE); inline constexpr u32 u16::BITS = u32(__private::num_bits<uint16_t>()); struct u64 final { uint64_t primitive_value{0u}; static constexpr auto MIN_PRIMITIVE = __private::min_value<uint64_t>(); static constexpr auto MAX_PRIMITIVE = __private::max_value<uint64_t>(); static const u64 MIN; static const u64 MAX; static const u32 BITS; constexpr inline u64() noexcept = default; template <Unsigned U> requires(::sus::mem::size_of<U>() <= ::sus::mem::size_of<uint64_t>()) constexpr inline u64(U v) noexcept : primitive_value(v.primitive_value) {} template <UnsignedPrimitiveInteger P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of<uint64_t>()) constexpr inline u64(P v) noexcept : primitive_value(v) {} template <UnsignedPrimitiveEnum P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of<uint64_t>()) constexpr inline u64(P v) noexcept : primitive_value(v) {} template <UnsignedPrimitiveEnumClass P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of<uint64_t>()) explicit constexpr inline u64(P v) noexcept : primitive_value(static_cast<uint64_t>(v)) {} template <Unsigned U> requires(::sus::mem::size_of<U>() <= ::sus::mem::size_of<uint64_t>()) constexpr inline u64& operator=(U v) noexcept { primitive_value = v.primitive_value; return *this; } template <UnsignedPrimitiveInteger P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of<uint64_t>()) constexpr inline u64& operator=(P v) noexcept { primitive_value = v; return *this; } template <UnsignedPrimitiveEnum P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of<uint64_t>()) constexpr inline u64& operator=(P v) noexcept { primitive_value = static_cast<uint64_t>(v); return *this; } template <Unsigned U> requires(::sus::mem::size_of<U>() <= ::sus::mem::size_of<uint64_t>()) __attribute__((pure)) static constexpr u64 from(U u) noexcept { return u64(static_cast<uint64_t>(u.primitive_value)); } template <Unsigned U> __attribute__((pure)) static constexpr ::sus::result::Result<u64, ::sus::num::TryFromIntError> try_from(U u) noexcept; template <UnsignedPrimitiveInteger U> requires(::sus::mem::size_of<U>() <= ::sus::mem::size_of<uint64_t>()) __attribute__((pure)) static constexpr u64 from(U u) noexcept { return u64(static_cast<uint64_t>(u)); } template <UnsignedPrimitiveInteger U> __attribute__((pure)) static constexpr ::sus::result::Result<u64, ::sus::num::TryFromIntError> try_from(U u) noexcept; template <Signed S> __attribute__((pure)) static constexpr ::sus::result::Result<u64, ::sus::num::TryFromIntError> try_from(S s) noexcept; template <SignedPrimitiveInteger S> __attribute__((pure)) static constexpr ::sus::result::Result<u64, ::sus::num::TryFromIntError> try_from(S s) noexcept; template <class S> requires(SignedPrimitiveEnum<S> || SignedPrimitiveEnumClass<S>) __attribute__((pure)) static constexpr ::sus::result::Result<u64, ::sus::num::TryFromIntError> try_from(S s) noexcept; template <class U> requires((UnsignedPrimitiveEnum<U> || UnsignedPrimitiveEnumClass<U>) && ::sus::mem::size_of<U>() <= ::sus::mem::size_of<uint64_t>()) __attribute__((pure)) static constexpr u64 from(U u) noexcept { return u64(static_cast<std::underlying_type_t<U>>(u)); } template <class U> requires(UnsignedPrimitiveEnum<U> || UnsignedPrimitiveEnumClass<U>) __attribute__((pure)) static constexpr ::sus::result::Result<u64, ::sus::num::TryFromIntError> try_from(U u) noexcept; static constexpr u64 from_product( ::sus::iter::Iterator<u64> auto&& it) noexcept { auto p = u64(uint64_t{1u}); for (u64 i : ::sus::move(it)) p *= i; return p; } static constexpr u64 from_sum( ::sus::iter::Iterator<u64> auto&& it) noexcept { auto p = u64(uint64_t{0u}); for (u64 i : ::sus::move(it)) p += i; return p; } template <UnsignedPrimitiveInteger U> requires(::sus::mem::size_of<U>() >= ::sus::mem::size_of<uint64_t>()) __attribute__((pure)) constexpr inline explicit operator U() const { return primitive_value; } [[nodiscard]] __attribute__((pure)) friend constexpr inline bool operator==( const u64& l, const u64& r) noexcept = default; template <UnsignedPrimitiveInteger P> [[nodiscard]] __attribute__((pure)) friend constexpr inline bool operator==( const u64& l, const P& r) noexcept { return l.primitive_value == r; } template <Unsigned U> [[nodiscard]] __attribute__((pure)) friend constexpr inline bool operator==( const u64& l, const U& r) noexcept { return l.primitive_value == r.primitive_value; } template <UnsignedPrimitiveInteger P> [[nodiscard]] __attribute__((pure)) friend constexpr inline std::strong_ordering operator<=>( const u64& l, const u64& r) noexcept { return l.primitive_value <=> r.primitive_value; } template <UnsignedPrimitiveInteger P> [[nodiscard]] __attribute__((pure)) friend constexpr inline std::strong_ordering operator<=>( const u64& l, const P& r) noexcept { return l.primitive_value <=> r; } template <Unsigned U> [[nodiscard]] __attribute__((pure)) friend constexpr inline std::strong_ordering operator<=>( const u64& l, const U& r) noexcept { return l.primitive_value <=> r.primitive_value; } __attribute__((pure)) constexpr inline u64 operator~() const& noexcept { return u64(__private::unchecked_not(primitive_value)); } [[nodiscard]] __attribute__((pure)) friend constexpr inline u64 operator+( const u64& l, const u64& r) noexcept { const auto out = __private::add_with_overflow(l.primitive_value, r.primitive_value); ::sus::check(!out.overflow); return u64(out.value); } [[nodiscard]] __attribute__((pure)) friend constexpr inline u64 operator-( const u64& l, const u64& r) noexcept { const auto out = __private::sub_with_overflow(l.primitive_value, r.primitive_value); ::sus::check(!out.overflow); return u64(out.value); } [[nodiscard]] __attribute__((pure)) friend constexpr inline u64 operator*( const u64& l, const u64& r) noexcept { const auto out = __private::mul_with_overflow(l.primitive_value, r.primitive_value); ::sus::check(!out.overflow); return u64(out.value); } [[nodiscard]] __attribute__((pure)) friend constexpr inline u64 operator/( const u64& l, const u64& r) noexcept { ::sus::check(r.primitive_value != 0u); return u64(__private::unchecked_div(l.primitive_value, r.primitive_value)); } [[nodiscard]] __attribute__((pure)) friend constexpr inline u64 operator%( const u64& l, const u64& r) noexcept { ::sus::check(r.primitive_value != 0u); return u64(__private::unchecked_rem(l.primitive_value, r.primitive_value)); } [[nodiscard]] __attribute__((pure)) friend constexpr inline u64 operator&( const u64& l, const u64& r) noexcept { return u64(__private::unchecked_and(l.primitive_value, r.primitive_value)); } [[nodiscard]] __attribute__((pure)) friend constexpr inline u64 operator|( const u64& l, const u64& r) noexcept { return u64(__private::unchecked_or(l.primitive_value, r.primitive_value)); } [[nodiscard]] __attribute__((pure)) friend constexpr inline u64 operator^( const u64& l, const u64& r) noexcept { return u64(__private::unchecked_xor(l.primitive_value, r.primitive_value)); } [[nodiscard]] __attribute__((pure)) friend constexpr inline u64 operator<<( const u64& l, const u32& r) noexcept { ::sus::check(r < BITS); return u64(__private::unchecked_shl(l.primitive_value, r.primitive_value)); } [[nodiscard]] __attribute__((pure)) friend constexpr inline u64 operator>>( const u64& l, const u32& r) noexcept { ::sus::check(r < BITS); return u64(__private::unchecked_shr(l.primitive_value, r.primitive_value)); } constexpr inline void operator+=(u64 r) & noexcept { const auto out = __private::add_with_overflow(primitive_value, r.primitive_value); ::sus::check(!out.overflow); primitive_value = out.value; } constexpr inline void operator-=(u64 r) & noexcept { const auto out = __private::sub_with_overflow(primitive_value, r.primitive_value); ::sus::check(!out.overflow); primitive_value = out.value; } constexpr inline void operator*=(u64 r) & noexcept { const auto out = __private::mul_with_overflow(primitive_value, r.primitive_value); ::sus::check(!out.overflow); primitive_value = out.value; } constexpr inline void operator/=(u64 r) & noexcept { ::sus::check(r.primitive_value != 0u); primitive_value /= r.primitive_value; } constexpr inline void operator%=(u64 r) & noexcept { ::sus::check(r.primitive_value != 0u); primitive_value %= r.primitive_value; } constexpr inline void operator&=(u64 r) & noexcept { primitive_value &= r.primitive_value; } constexpr inline void operator|=(u64 r) & noexcept { primitive_value |= r.primitive_value; } constexpr inline void operator^=(u64 r) & noexcept { primitive_value ^= r.primitive_value; } constexpr inline void operator<<=(const u32& r) & noexcept { ::sus::check(r < BITS); primitive_value <<= r.primitive_value; } constexpr inline void operator>>=(const u32& r) & noexcept { ::sus::check(r < BITS); primitive_value >>= r.primitive_value; } __attribute__((pure)) constexpr u64 abs_diff(const u64& r) const& noexcept { if (primitive_value >= r.primitive_value) return u64(__private::unchecked_sub(primitive_value, r.primitive_value)); else return u64(__private::unchecked_sub(r.primitive_value, primitive_value)); } __attribute__((pure)) constexpr ::sus::option::Option<u64> checked_add( const u64& rhs) const& noexcept; template <std::convertible_to<i64> S> __attribute__((pure)) constexpr ::sus::option::Option<u64> checked_add_signed( const S& rhs) const& noexcept; __attribute__((pure)) constexpr sus::tuple_type::Tuple<u64, bool> overflowing_add( const u64& rhs) const& noexcept; template <std::convertible_to<i64> S> __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u64, bool> overflowing_add_signed( const S& rhs) const& noexcept; __attribute__((pure)) constexpr u64 saturating_add(const u64& rhs) const& noexcept { return u64(__private::saturating_add(primitive_value, rhs.primitive_value)); } template <std::convertible_to<i64> S> __attribute__((pure)) constexpr u64 saturating_add_signed(const S& rhs) const& noexcept { const auto r = __private::add_with_overflow_signed(primitive_value, rhs.primitive_value); if (!r.overflow) [[likely]] return r.value; else { if (rhs.primitive_value >= 0) return MAX; else return MIN; } } __attribute__((pure)) inline constexpr u64 unchecked_add( ::sus::marker::UnsafeFnMarker, const u64& rhs) const& noexcept { return u64(__private::unchecked_add(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr u64 wrapping_add(const u64& rhs) const& noexcept { return u64(__private::wrapping_add(primitive_value, rhs.primitive_value)); } template <std::convertible_to<i64> S> __attribute__((pure)) constexpr u64 wrapping_add_signed(const S& rhs) const& noexcept { return __private::add_with_overflow_signed(primitive_value, rhs.primitive_value) .value; } __attribute__((pure)) constexpr ::sus::option::Option<u64> checked_div( const u64& rhs) const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u64, bool> overflowing_div( const u64& rhs) const& noexcept; __attribute__((pure)) constexpr u64 saturating_div(const u64& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return u64(__private::unchecked_div(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr u64 wrapping_div(const u64& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return u64(__private::unchecked_div(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr ::sus::option::Option<u64> checked_mul( const u64& rhs) const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u64, bool> overflowing_mul( const u64& rhs) const& noexcept; __attribute__((pure)) constexpr u64 saturating_mul(const u64& rhs) const& noexcept { return u64(__private::saturating_mul(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr u64 unchecked_mul(::sus::marker::UnsafeFnMarker, const u64& rhs) const& noexcept { return u64(__private::unchecked_mul(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr u64 wrapping_mul(const u64& rhs) const& noexcept { return u64(__private::wrapping_mul(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr ::sus::option::Option<u64> checked_neg() const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u64, bool> overflowing_neg() const& noexcept; __attribute__((pure)) constexpr u64 wrapping_neg() const& noexcept { return (u64(uint64_t{0u})).wrapping_sub(*this); } __attribute__((pure)) constexpr ::sus::option::Option<u64> checked_rem( const u64& rhs) const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u64, bool> overflowing_rem( const u64& rhs) const& noexcept; __attribute__((pure)) constexpr u64 wrapping_rem(const u64& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return u64(__private::unchecked_rem(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr u64 div_euclid(const u64& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return u64(__private::unchecked_div(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr ::sus::option::Option<u64> checked_div_euclid( const u64& rhs) const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u64, bool> overflowing_div_euclid( const u64& rhs) const& noexcept; __attribute__((pure)) constexpr u64 wrapping_div_euclid(const u64& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return u64(__private::unchecked_div(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr u64 rem_euclid(const u64& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return u64(__private::unchecked_rem(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr ::sus::option::Option<u64> checked_rem_euclid( const u64& rhs) const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u64, bool> overflowing_rem_euclid( const u64& rhs) const& noexcept; __attribute__((pure)) constexpr u64 wrapping_rem_euclid(const u64& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return u64(__private::unchecked_rem(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr ::sus::option::Option<u64> checked_shl( const u32& rhs) const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u64, bool> overflowing_shl( const u32& rhs) const& noexcept; __attribute__((pure)) constexpr u64 wrapping_shl(const u32& rhs) const& noexcept { return u64( __private::shl_with_overflow(primitive_value, rhs.primitive_value).value); } __attribute__((pure)) constexpr ::sus::option::Option<u64> checked_shr( const u32& rhs) const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u64, bool> overflowing_shr( const u32& rhs) const& noexcept; __attribute__((pure)) constexpr u64 wrapping_shr(const u32& rhs) const& noexcept { return u64( __private::shr_with_overflow(primitive_value, rhs.primitive_value).value); } __attribute__((pure)) constexpr ::sus::option::Option<u64> checked_sub( const u64& rhs) const&; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u64, bool> overflowing_sub( const u64& rhs) const& noexcept; __attribute__((pure)) constexpr u64 saturating_sub(const u64& rhs) const& { return u64(__private::saturating_sub(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr u64 unchecked_sub(::sus::marker::UnsafeFnMarker, const u64& rhs) const& noexcept { return u64(__private::unchecked_sub(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr u64 wrapping_sub(const u64& rhs) const& noexcept { return u64(__private::wrapping_sub(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr u32 count_ones() const& noexcept { return __private::count_ones(primitive_value); } __attribute__((pure)) constexpr u32 count_zeros() const& noexcept { return (~(*this)).count_ones(); } __attribute__((pure)) constexpr u32 leading_ones() const& noexcept { return (~(*this)).leading_zeros(); } __attribute__((pure)) constexpr u32 leading_zeros() const& noexcept { return __private::leading_zeros(primitive_value); } __attribute__((pure)) constexpr u32 trailing_ones() const& noexcept { return (~(*this)).trailing_zeros(); } __attribute__((pure)) constexpr u32 trailing_zeros() const& noexcept { return __private::trailing_zeros(primitive_value); } __attribute__((pure)) constexpr u64 reverse_bits() const& noexcept { return u64(__private::reverse_bits(primitive_value)); } __attribute__((pure)) constexpr u64 rotate_left(const u32& n) const& noexcept { return u64(__private::rotate_left(primitive_value, n.primitive_value)); } __attribute__((pure)) constexpr u64 rotate_right(const u32& n) const& noexcept { return u64(__private::rotate_right(primitive_value, n.primitive_value)); } __attribute__((pure)) constexpr u64 swap_bytes() const& noexcept { return u64(__private::swap_bytes(primitive_value)); } __attribute__((pure)) constexpr u64 pow(const u32& rhs) const& noexcept { const auto out = __private::pow_with_overflow(primitive_value, rhs.primitive_value); ::sus::check(!out.overflow); return u64(out.value); } __attribute__((pure)) constexpr ::sus::option::Option<u64> checked_pow( const u32& rhs) const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u64, bool> overflowing_pow( const u32& exp) const& noexcept; __attribute__((pure)) constexpr u64 wrapping_pow(const u32& exp) const& noexcept { return u64(__private::wrapping_pow(primitive_value, exp.primitive_value)); } __attribute__((pure)) constexpr ::sus::option::Option<u32> checked_log2() const& noexcept; __attribute__((pure)) constexpr u32 log2() const& noexcept; __attribute__((pure)) constexpr ::sus::option::Option<u32> checked_log10() const& noexcept; __attribute__((pure)) constexpr u32 log10() const& noexcept; __attribute__((pure)) constexpr ::sus::option::Option<u32> checked_log( const u64& base) const& noexcept; __attribute__((pure)) constexpr u32 log(const u64& base) const& noexcept; __attribute__((pure)) constexpr bool is_power_of_two() const& noexcept { return count_ones() == u64(uint64_t{1u}); } __attribute__((pure)) constexpr u64 next_power_of_two() const& noexcept { const auto one_less = __private::one_less_than_next_power_of_two(primitive_value); return u64(one_less) + u64(uint64_t{1u}); } __attribute__((pure)) constexpr ::sus::option::Option<u64> checked_next_power_of_two() const& noexcept; __attribute__((pure)) constexpr u64 wrapping_next_power_of_two() const& noexcept { const auto one_less = __private::one_less_than_next_power_of_two(primitive_value); return u64(one_less).wrapping_add(u64(uint64_t{1u})); } [[nodiscard]] __attribute__((pure)) static constexpr u64 from_be(const u64& x) noexcept { if constexpr (::sus::assertions::is_big_endian()) return x; else return x.swap_bytes(); } [[nodiscard]] __attribute__((pure)) static constexpr u64 from_le(const u64& x) noexcept { if constexpr (::sus::assertions::is_little_endian()) return x; else return x.swap_bytes(); } __attribute__((pure)) constexpr u64 to_be() const& noexcept { if constexpr (::sus::assertions::is_big_endian()) return *this; else return swap_bytes(); } __attribute__((pure)) constexpr u64 to_le() const& noexcept { if constexpr (::sus::assertions::is_little_endian()) return *this; else return swap_bytes(); } __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<uint64_t>()> to_be_bytes() const& noexcept; __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<uint64_t>()> to_le_bytes() const& noexcept; __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<uint64_t>()> to_ne_bytes() const& noexcept; [[nodiscard]] __attribute__((pure)) static constexpr u64 from_be_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<uint64_t>()>& bytes) noexcept; [[nodiscard]] __attribute__((pure)) static constexpr u64 from_le_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<uint64_t>()>& bytes) noexcept; [[nodiscard]] __attribute__((pure)) static constexpr u64 from_ne_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<uint64_t>()>& bytes) noexcept; }; inline constexpr u64 u64::MIN = u64(u64::MIN_PRIMITIVE); inline constexpr u64 u64::MAX = u64(u64::MAX_PRIMITIVE); inline constexpr u32 u64::BITS = u32(__private::num_bits<uint64_t>()); struct usize final { ::sus::num::__private::addr_type<>::unsigned_type primitive_value{0u}; static constexpr auto MIN_PRIMITIVE = __private::min_value< ::sus::num::__private::addr_type<>::unsigned_type>(); static constexpr auto MAX_PRIMITIVE = __private::max_value< ::sus::num::__private::addr_type<>::unsigned_type>(); static const usize MIN; static const usize MAX; static const u32 BITS; constexpr inline usize() noexcept = default; template <Unsigned U> requires(::sus::mem::size_of<U>() <= ::sus::mem::size_of< ::sus::num::__private::addr_type<>::unsigned_type>()) constexpr inline usize(U v) noexcept : primitive_value(v.primitive_value) {} template <UnsignedPrimitiveInteger P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of< ::sus::num::__private::addr_type<>::unsigned_type>()) constexpr inline usize(P v) noexcept : primitive_value(v) {} template <UnsignedPrimitiveEnum P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of< ::sus::num::__private::addr_type<>::unsigned_type>()) constexpr inline usize(P v) noexcept : primitive_value(v) {} template <UnsignedPrimitiveEnumClass P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of< ::sus::num::__private::addr_type<>::unsigned_type>()) explicit constexpr inline usize(P v) noexcept : primitive_value(static_cast< ::sus::num::__private::addr_type<>::unsigned_type>(v)) {} template <Unsigned U> requires(::sus::mem::size_of<U>() <= ::sus::mem::size_of< ::sus::num::__private::addr_type<>::unsigned_type>()) constexpr inline usize& operator=(U v) noexcept { primitive_value = v.primitive_value; return *this; } template <UnsignedPrimitiveInteger P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of< ::sus::num::__private::addr_type<>::unsigned_type>()) constexpr inline usize& operator=(P v) noexcept { primitive_value = v; return *this; } template <UnsignedPrimitiveEnum P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of< ::sus::num::__private::addr_type<>::unsigned_type>()) constexpr inline usize& operator=(P v) noexcept { primitive_value = static_cast< ::sus::num::__private::addr_type<>::unsigned_type>(v); return *this; } template <Unsigned U> requires(::sus::mem::size_of<U>() <= ::sus::mem::size_of< ::sus::num::__private::addr_type<>::unsigned_type>()) __attribute__((pure)) static constexpr usize from(U u) noexcept { return usize(static_cast< ::sus::num::__private::addr_type<>::unsigned_type>(u.primitive_value)); } template <Unsigned U> __attribute__((pure)) static constexpr ::sus::result::Result<usize, ::sus::num::TryFromIntError> try_from(U u) noexcept; template <UnsignedPrimitiveInteger U> requires(::sus::mem::size_of<U>() <= ::sus::mem::size_of< ::sus::num::__private::addr_type<>::unsigned_type>()) __attribute__((pure)) static constexpr usize from(U u) noexcept { return usize(static_cast< ::sus::num::__private::addr_type<>::unsigned_type>(u)); } template <UnsignedPrimitiveInteger U> __attribute__((pure)) static constexpr ::sus::result::Result<usize, ::sus::num::TryFromIntError> try_from(U u) noexcept; template <Signed S> __attribute__((pure)) static constexpr ::sus::result::Result<usize, ::sus::num::TryFromIntError> try_from(S s) noexcept; template <SignedPrimitiveInteger S> __attribute__((pure)) static constexpr ::sus::result::Result<usize, ::sus::num::TryFromIntError> try_from(S s) noexcept; template <class S> requires(SignedPrimitiveEnum<S> || SignedPrimitiveEnumClass<S>) __attribute__((pure)) static constexpr ::sus::result::Result<usize, ::sus::num::TryFromIntError> try_from(S s) noexcept; template <class U> requires((UnsignedPrimitiveEnum<U> || UnsignedPrimitiveEnumClass<U>) && ::sus::mem::size_of<U>() <= ::sus::mem::size_of< ::sus::num::__private::addr_type<>::unsigned_type>()) __attribute__((pure)) static constexpr usize from(U u) noexcept { return usize(static_cast<std::underlying_type_t<U>>(u)); } template <class U> requires(UnsignedPrimitiveEnum<U> || UnsignedPrimitiveEnumClass<U>) __attribute__((pure)) static constexpr ::sus::result::Result<usize, ::sus::num::TryFromIntError> try_from(U u) noexcept; static constexpr usize from_product( ::sus::iter::Iterator<usize> auto&& it) noexcept { auto p = usize(::sus::num::__private::addr_type<>::unsigned_type{1u}); for (usize i : ::sus::move(it)) p *= i; return p; } static constexpr usize from_sum( ::sus::iter::Iterator<usize> auto&& it) noexcept { auto p = usize(::sus::num::__private::addr_type<>::unsigned_type{0u}); for (usize i : ::sus::move(it)) p += i; return p; } template <UnsignedPrimitiveInteger U> requires(::sus::mem::size_of<U>() >= ::sus::mem::size_of< ::sus::num::__private::addr_type<>::unsigned_type>()) __attribute__((pure)) constexpr inline explicit operator U() const { return primitive_value; } [[nodiscard]] __attribute__((pure)) friend constexpr inline bool operator==( const usize& l, const usize& r) noexcept = default; template <UnsignedPrimitiveInteger P> [[nodiscard]] __attribute__((pure)) friend constexpr inline bool operator==( const usize& l, const P& r) noexcept { return l.primitive_value == r; } template <Unsigned U> [[nodiscard]] __attribute__((pure)) friend constexpr inline bool operator==( const usize& l, const U& r) noexcept { return l.primitive_value == r.primitive_value; } template <UnsignedPrimitiveInteger P> [[nodiscard]] __attribute__((pure)) friend constexpr inline std::strong_ordering operator<=>( const usize& l, const usize& r) noexcept { return l.primitive_value <=> r.primitive_value; } template <UnsignedPrimitiveInteger P> [[nodiscard]] __attribute__((pure)) friend constexpr inline std::strong_ordering operator<=>( const usize& l, const P& r) noexcept { return l.primitive_value <=> r; } template <Unsigned U> [[nodiscard]] __attribute__((pure)) friend constexpr inline std::strong_ordering operator<=>( const usize& l, const U& r) noexcept { return l.primitive_value <=> r.primitive_value; } __attribute__((pure)) constexpr inline usize operator~() const& noexcept { return usize(__private::unchecked_not(primitive_value)); } [[nodiscard]] __attribute__((pure)) friend constexpr inline usize operator+( const usize& l, const usize& r) noexcept { const auto out = __private::add_with_overflow(l.primitive_value, r.primitive_value); ::sus::check(!out.overflow); return usize(out.value); } [[nodiscard]] __attribute__((pure)) friend constexpr inline usize operator-( const usize& l, const usize& r) noexcept { const auto out = __private::sub_with_overflow(l.primitive_value, r.primitive_value); ::sus::check(!out.overflow); return usize(out.value); } [[nodiscard]] __attribute__((pure)) friend constexpr inline usize operator*( const usize& l, const usize& r) noexcept { const auto out = __private::mul_with_overflow(l.primitive_value, r.primitive_value); ::sus::check(!out.overflow); return usize(out.value); } [[nodiscard]] __attribute__((pure)) friend constexpr inline usize operator/( const usize& l, const usize& r) noexcept { ::sus::check(r.primitive_value != 0u); return usize(__private::unchecked_div(l.primitive_value, r.primitive_value)); } [[nodiscard]] __attribute__((pure)) friend constexpr inline usize operator%( const usize& l, const usize& r) noexcept { ::sus::check(r.primitive_value != 0u); return usize(__private::unchecked_rem(l.primitive_value, r.primitive_value)); } [[nodiscard]] __attribute__((pure)) friend constexpr inline usize operator&( const usize& l, const usize& r) noexcept { return usize(__private::unchecked_and(l.primitive_value, r.primitive_value)); } [[nodiscard]] __attribute__((pure)) friend constexpr inline usize operator|( const usize& l, const usize& r) noexcept { return usize(__private::unchecked_or(l.primitive_value, r.primitive_value)); } [[nodiscard]] __attribute__((pure)) friend constexpr inline usize operator^( const usize& l, const usize& r) noexcept { return usize(__private::unchecked_xor(l.primitive_value, r.primitive_value)); } [[nodiscard]] __attribute__((pure)) friend constexpr inline usize operator<<( const usize& l, const u32& r) noexcept { ::sus::check(r < BITS); return usize(__private::unchecked_shl(l.primitive_value, r.primitive_value)); } [[nodiscard]] __attribute__((pure)) friend constexpr inline usize operator>>( const usize& l, const u32& r) noexcept { ::sus::check(r < BITS); return usize(__private::unchecked_shr(l.primitive_value, r.primitive_value)); } constexpr inline void operator+=(usize r) & noexcept { const auto out = __private::add_with_overflow(primitive_value, r.primitive_value); ::sus::check(!out.overflow); primitive_value = out.value; } constexpr inline void operator-=(usize r) & noexcept { const auto out = __private::sub_with_overflow(primitive_value, r.primitive_value); ::sus::check(!out.overflow); primitive_value = out.value; } constexpr inline void operator*=(usize r) & noexcept { const auto out = __private::mul_with_overflow(primitive_value, r.primitive_value); ::sus::check(!out.overflow); primitive_value = out.value; } constexpr inline void operator/=(usize r) & noexcept { ::sus::check(r.primitive_value != 0u); primitive_value /= r.primitive_value; } constexpr inline void operator%=(usize r) & noexcept { ::sus::check(r.primitive_value != 0u); primitive_value %= r.primitive_value; } constexpr inline void operator&=(usize r) & noexcept { primitive_value &= r.primitive_value; } constexpr inline void operator|=(usize r) & noexcept { primitive_value |= r.primitive_value; } constexpr inline void operator^=(usize r) & noexcept { primitive_value ^= r.primitive_value; } constexpr inline void operator<<=(const u32& r) & noexcept { ::sus::check(r < BITS); primitive_value <<= r.primitive_value; } constexpr inline void operator>>=(const u32& r) & noexcept { ::sus::check(r < BITS); primitive_value >>= r.primitive_value; } __attribute__((pure)) constexpr usize abs_diff(const usize& r) const& noexcept { if (primitive_value >= r.primitive_value) return usize(__private::unchecked_sub(primitive_value, r.primitive_value)); else return usize(__private::unchecked_sub(r.primitive_value, primitive_value)); } __attribute__((pure)) constexpr ::sus::option::Option<usize> checked_add( const usize& rhs) const& noexcept; template <std::convertible_to<isize> S> __attribute__((pure)) constexpr ::sus::option::Option<usize> checked_add_signed( const S& rhs) const& noexcept; __attribute__((pure)) constexpr sus::tuple_type::Tuple<usize, bool> overflowing_add( const usize& rhs) const& noexcept; template <std::convertible_to<isize> S> __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<usize, bool> overflowing_add_signed( const S& rhs) const& noexcept; __attribute__((pure)) constexpr usize saturating_add(const usize& rhs) const& noexcept { return usize(__private::saturating_add(primitive_value, rhs.primitive_value)); } template <std::convertible_to<isize> S> __attribute__((pure)) constexpr usize saturating_add_signed(const S& rhs) const& noexcept { const auto r = __private::add_with_overflow_signed(primitive_value, rhs.primitive_value); if (!r.overflow) [[likely]] return r.value; else { if (rhs.primitive_value >= 0) return MAX; else return MIN; } } __attribute__((pure)) inline constexpr usize unchecked_add( ::sus::marker::UnsafeFnMarker, const usize& rhs) const& noexcept { return usize(__private::unchecked_add(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr usize wrapping_add(const usize& rhs) const& noexcept { return usize(__private::wrapping_add(primitive_value, rhs.primitive_value)); } template <std::convertible_to<isize> S> __attribute__((pure)) constexpr usize wrapping_add_signed(const S& rhs) const& noexcept { return __private::add_with_overflow_signed(primitive_value, rhs.primitive_value) .value; } __attribute__((pure)) constexpr ::sus::option::Option<usize> checked_div( const usize& rhs) const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<usize, bool> overflowing_div( const usize& rhs) const& noexcept; __attribute__((pure)) constexpr usize saturating_div(const usize& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return usize(__private::unchecked_div(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr usize wrapping_div(const usize& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return usize(__private::unchecked_div(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr ::sus::option::Option<usize> checked_mul( const usize& rhs) const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<usize, bool> overflowing_mul( const usize& rhs) const& noexcept; __attribute__((pure)) constexpr usize saturating_mul(const usize& rhs) const& noexcept { return usize(__private::saturating_mul(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr usize unchecked_mul(::sus::marker::UnsafeFnMarker, const usize& rhs) const& noexcept { return usize(__private::unchecked_mul(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr usize wrapping_mul(const usize& rhs) const& noexcept { return usize(__private::wrapping_mul(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr ::sus::option::Option<usize> checked_neg() const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<usize, bool> overflowing_neg() const& noexcept; __attribute__((pure)) constexpr usize wrapping_neg() const& noexcept { return (usize(::sus::num::__private::addr_type<>::unsigned_type{0u})).wrapping_sub(*this); } __attribute__((pure)) constexpr ::sus::option::Option<usize> checked_rem( const usize& rhs) const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<usize, bool> overflowing_rem( const usize& rhs) const& noexcept; __attribute__((pure)) constexpr usize wrapping_rem(const usize& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return usize(__private::unchecked_rem(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr usize div_euclid(const usize& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return usize(__private::unchecked_div(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr ::sus::option::Option<usize> checked_div_euclid( const usize& rhs) const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<usize, bool> overflowing_div_euclid( const usize& rhs) const& noexcept; __attribute__((pure)) constexpr usize wrapping_div_euclid(const usize& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return usize(__private::unchecked_div(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr usize rem_euclid(const usize& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return usize(__private::unchecked_rem(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr ::sus::option::Option<usize> checked_rem_euclid( const usize& rhs) const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<usize, bool> overflowing_rem_euclid( const usize& rhs) const& noexcept; __attribute__((pure)) constexpr usize wrapping_rem_euclid(const usize& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return usize(__private::unchecked_rem(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr ::sus::option::Option<usize> checked_shl( const u32& rhs) const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<usize, bool> overflowing_shl( const u32& rhs) const& noexcept; __attribute__((pure)) constexpr usize wrapping_shl(const u32& rhs) const& noexcept { return usize( __private::shl_with_overflow(primitive_value, rhs.primitive_value).value); } __attribute__((pure)) constexpr ::sus::option::Option<usize> checked_shr( const u32& rhs) const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<usize, bool> overflowing_shr( const u32& rhs) const& noexcept; __attribute__((pure)) constexpr usize wrapping_shr(const u32& rhs) const& noexcept { return usize( __private::shr_with_overflow(primitive_value, rhs.primitive_value).value); } __attribute__((pure)) constexpr ::sus::option::Option<usize> checked_sub( const usize& rhs) const&; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<usize, bool> overflowing_sub( const usize& rhs) const& noexcept; __attribute__((pure)) constexpr usize saturating_sub(const usize& rhs) const& { return usize(__private::saturating_sub(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr usize unchecked_sub(::sus::marker::UnsafeFnMarker, const usize& rhs) const& noexcept { return usize(__private::unchecked_sub(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr usize wrapping_sub(const usize& rhs) const& noexcept { return usize(__private::wrapping_sub(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr u32 count_ones() const& noexcept { return __private::count_ones(primitive_value); } __attribute__((pure)) constexpr u32 count_zeros() const& noexcept { return (~(*this)).count_ones(); } __attribute__((pure)) constexpr u32 leading_ones() const& noexcept { return (~(*this)).leading_zeros(); } __attribute__((pure)) constexpr u32 leading_zeros() const& noexcept { return __private::leading_zeros(primitive_value); } __attribute__((pure)) constexpr u32 trailing_ones() const& noexcept { return (~(*this)).trailing_zeros(); } __attribute__((pure)) constexpr u32 trailing_zeros() const& noexcept { return __private::trailing_zeros(primitive_value); } __attribute__((pure)) constexpr usize reverse_bits() const& noexcept { return usize(__private::reverse_bits(primitive_value)); } __attribute__((pure)) constexpr usize rotate_left(const u32& n) const& noexcept { return usize(__private::rotate_left(primitive_value, n.primitive_value)); } __attribute__((pure)) constexpr usize rotate_right(const u32& n) const& noexcept { return usize(__private::rotate_right(primitive_value, n.primitive_value)); } __attribute__((pure)) constexpr usize swap_bytes() const& noexcept { return usize(__private::swap_bytes(primitive_value)); } __attribute__((pure)) constexpr usize pow(const u32& rhs) const& noexcept { const auto out = __private::pow_with_overflow(primitive_value, rhs.primitive_value); ::sus::check(!out.overflow); return usize(out.value); } __attribute__((pure)) constexpr ::sus::option::Option<usize> checked_pow( const u32& rhs) const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<usize, bool> overflowing_pow( const u32& exp) const& noexcept; __attribute__((pure)) constexpr usize wrapping_pow(const u32& exp) const& noexcept { return usize(__private::wrapping_pow(primitive_value, exp.primitive_value)); } __attribute__((pure)) constexpr ::sus::option::Option<u32> checked_log2() const& noexcept; __attribute__((pure)) constexpr u32 log2() const& noexcept; __attribute__((pure)) constexpr ::sus::option::Option<u32> checked_log10() const& noexcept; __attribute__((pure)) constexpr u32 log10() const& noexcept; __attribute__((pure)) constexpr ::sus::option::Option<u32> checked_log( const usize& base) const& noexcept; __attribute__((pure)) constexpr u32 log(const usize& base) const& noexcept; __attribute__((pure)) constexpr bool is_power_of_two() const& noexcept { return count_ones() == usize(::sus::num::__private::addr_type<>::unsigned_type{1u}); } __attribute__((pure)) constexpr usize next_power_of_two() const& noexcept { const auto one_less = __private::one_less_than_next_power_of_two(primitive_value); return usize(one_less) + usize(::sus::num::__private::addr_type<>::unsigned_type{1u}); } __attribute__((pure)) constexpr ::sus::option::Option<usize> checked_next_power_of_two() const& noexcept; __attribute__((pure)) constexpr usize wrapping_next_power_of_two() const& noexcept { const auto one_less = __private::one_less_than_next_power_of_two(primitive_value); return usize(one_less).wrapping_add(usize(::sus::num::__private::addr_type<>::unsigned_type{1u})); } [[nodiscard]] __attribute__((pure)) static constexpr usize from_be(const usize& x) noexcept { if constexpr (::sus::assertions::is_big_endian()) return x; else return x.swap_bytes(); } [[nodiscard]] __attribute__((pure)) static constexpr usize from_le(const usize& x) noexcept { if constexpr (::sus::assertions::is_little_endian()) return x; else return x.swap_bytes(); } __attribute__((pure)) constexpr usize to_be() const& noexcept { if constexpr (::sus::assertions::is_big_endian()) return *this; else return swap_bytes(); } __attribute__((pure)) constexpr usize to_le() const& noexcept { if constexpr (::sus::assertions::is_little_endian()) return *this; else return swap_bytes(); } __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of< ::sus::num::__private::addr_type<>::unsigned_type>()> to_be_bytes() const& noexcept; __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of< ::sus::num::__private::addr_type<>::unsigned_type>()> to_le_bytes() const& noexcept; __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of< ::sus::num::__private::addr_type<>::unsigned_type>()> to_ne_bytes() const& noexcept; [[nodiscard]] __attribute__((pure)) static constexpr usize from_be_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of< ::sus::num::__private::addr_type<>::unsigned_type>()>& bytes) noexcept; [[nodiscard]] __attribute__((pure)) static constexpr usize from_le_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of< ::sus::num::__private::addr_type<>::unsigned_type>()>& bytes) noexcept; [[nodiscard]] __attribute__((pure)) static constexpr usize from_ne_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of< ::sus::num::__private::addr_type<>::unsigned_type>()>& bytes) noexcept; }; inline constexpr usize usize::MIN = usize(usize::MIN_PRIMITIVE); inline constexpr usize usize::MAX = usize(usize::MAX_PRIMITIVE); inline constexpr u32 usize::BITS = u32(__private::num_bits< ::sus::num::__private::addr_type<>::unsigned_type>()); struct uptr final { ::sus::num::__private::ptr_type<>::unsigned_type primitive_value{0u}; static constexpr auto MIN_PRIMITIVE = __private::min_value< ::sus::num::__private::ptr_type<>::unsigned_type>(); static constexpr auto MAX_PRIMITIVE = __private::max_value< ::sus::num::__private::ptr_type<>::unsigned_type>(); static const uptr MIN; static const uptr MAX_ADDR; static const uptr MAX_BIT_PATTERN; static const u32 BITS; constexpr inline uptr() noexcept = default; template <class T> explicit uptr(T* v) noexcept : primitive_value(reinterpret_cast< ::sus::num::__private::ptr_type<>::unsigned_type>(v)) {} explicit constexpr uptr(std::same_as<std::nullptr_t> auto) noexcept : primitive_value(0u) {} template <Unsigned U> requires(::sus::mem::size_of<U>() == ::sus::mem::size_of< ::sus::num::__private::ptr_type<>::unsigned_type>()) explicit constexpr inline uptr(U v) noexcept : primitive_value(v.primitive_value) {} template <UnsignedPrimitiveInteger P> requires(::sus::mem::size_of<P>() == ::sus::mem::size_of< ::sus::num::__private::ptr_type<>::unsigned_type>()) explicit constexpr inline uptr(P v) noexcept : primitive_value(v) {} template <class T> uptr& operator=(T* v) noexcept { primitive_value = reinterpret_cast< ::sus::num::__private::ptr_type<>::unsigned_type>(v); return *this; } constexpr uptr& operator=(std::same_as<std::nullptr_t> auto) noexcept { primitive_value = 0u; return *this; } template <Unsigned U> requires(::sus::mem::size_of<U>() == ::sus::mem::size_of< ::sus::num::__private::ptr_type<>::unsigned_type>()) constexpr inline uptr& operator=(U v) noexcept { primitive_value = v.primitive_value; return *this; } template <UnsignedPrimitiveInteger P> requires(::sus::mem::size_of<P>() == ::sus::mem::size_of< ::sus::num::__private::ptr_type<>::unsigned_type>()) constexpr inline uptr& operator=(P v) noexcept { primitive_value = v; return *this; } uptr with_addr(usize addr) const& noexcept { ::sus::num::__private::ptr_type<>::unsigned_type p = ::sus::num::__private::ptr_type<>::unsigned_type{addr}; if constexpr (::sus::mem::size_of<uptr>() != ::sus::mem::size_of<usize>()) { constexpr ::sus::num::__private::ptr_type<>::unsigned_type mask = uptr::MAX_PRIMITIVE - ::sus::num::__private::ptr_type<>::unsigned_type{usize::MAX_PRIMITIVE}; p |= mask & primitive_value; } return uptr(p); } template <class U> __attribute__((pure)) static uptr from(U* u) noexcept { return uptr(reinterpret_cast< ::sus::num::__private::ptr_type<>::unsigned_type>(u)); } template <class U> __attribute__((pure)) static constexpr ::sus::result::Result<uptr, ::sus::num::TryFromIntError> try_from(U* u) noexcept; template <Unsigned U> requires(::sus::mem::size_of<U>() == ::sus::mem::size_of< ::sus::num::__private::ptr_type<>::unsigned_type>()) __attribute__((pure)) static constexpr uptr from(U u) noexcept { if constexpr (MAX_PRIMITIVE < U::MAX_PRIMITIVE) ::sus::check(u.primitive_value <= MAX_PRIMITIVE); return uptr(static_cast< ::sus::num::__private::ptr_type<>::unsigned_type>(u.primitive_value)); } template <Unsigned U> requires(::sus::mem::size_of<U>() == ::sus::mem::size_of< ::sus::num::__private::ptr_type<>::unsigned_type>()) __attribute__((pure)) static constexpr ::sus::result::Result<uptr, ::sus::num::TryFromIntError> try_from(U u) noexcept; template <UnsignedPrimitiveInteger U> requires(::sus::mem::size_of<U>() == ::sus::mem::size_of< ::sus::num::__private::ptr_type<>::unsigned_type>()) __attribute__((pure)) static constexpr uptr from(U u) noexcept { if constexpr (MAX_PRIMITIVE < __private::max_value<U>()) ::sus::check(u <= MAX_PRIMITIVE); return uptr(static_cast< ::sus::num::__private::ptr_type<>::unsigned_type>(u)); } template <UnsignedPrimitiveInteger U> requires(::sus::mem::size_of<U>() == ::sus::mem::size_of< ::sus::num::__private::ptr_type<>::unsigned_type>()) __attribute__((pure)) static constexpr ::sus::result::Result<uptr, ::sus::num::TryFromIntError> try_from(U u) noexcept; static constexpr uptr from_product( ::sus::iter::Iterator<uptr> auto&& it) noexcept { auto p = uptr(::sus::num::__private::ptr_type<>::unsigned_type{1u}); for (uptr i : ::sus::move(it)) p *= i; return p; } static constexpr uptr from_sum( ::sus::iter::Iterator<uptr> auto&& it) noexcept { auto p = uptr(::sus::num::__private::ptr_type<>::unsigned_type{0u}); for (uptr i : ::sus::move(it)) p += i; return p; } template <std::same_as<uintptr_t> U> __attribute__((pure)) constexpr inline explicit operator U() const { return static_cast<uintptr_t>(primitive_value); } [[nodiscard]] __attribute__((pure)) friend constexpr inline bool operator==( const uptr& l, const uptr& r) noexcept = default; template <UnsignedPrimitiveInteger P> [[nodiscard]] __attribute__((pure)) friend constexpr inline bool operator==( const uptr& l, const P& r) noexcept { return l.primitive_value == r; } template <Unsigned U> [[nodiscard]] __attribute__((pure)) friend constexpr inline bool operator==( const uptr& l, const U& r) noexcept { return l.primitive_value == r.primitive_value; } template <UnsignedPrimitiveInteger P> [[nodiscard]] __attribute__((pure)) friend constexpr inline std::strong_ordering operator<=>( const uptr& l, const uptr& r) noexcept { return l.primitive_value <=> r.primitive_value; } template <UnsignedPrimitiveInteger P> [[nodiscard]] __attribute__((pure)) friend constexpr inline std::strong_ordering operator<=>( const uptr& l, const P& r) noexcept { return l.primitive_value <=> r; } template <Unsigned U> [[nodiscard]] __attribute__((pure)) friend constexpr inline std::strong_ordering operator<=>( const uptr& l, const U& r) noexcept { return l.primitive_value <=> r.primitive_value; } __attribute__((pure)) constexpr inline uptr operator~() const& noexcept { return uptr(__private::unchecked_not(primitive_value)); } [[nodiscard]] __attribute__((pure)) friend constexpr inline uptr operator+( const uptr& l, const uptr& r) noexcept { const auto out = __private::add_with_overflow(l.primitive_value, r.primitive_value); ::sus::check(!out.overflow); return uptr(out.value); } [[nodiscard]] __attribute__((pure)) friend constexpr inline uptr operator-( const uptr& l, const uptr& r) noexcept { const auto out = __private::sub_with_overflow(l.primitive_value, r.primitive_value); ::sus::check(!out.overflow); return uptr(out.value); } [[nodiscard]] __attribute__((pure)) friend constexpr inline uptr operator*( const uptr& l, const uptr& r) noexcept { const auto out = __private::mul_with_overflow(l.primitive_value, r.primitive_value); ::sus::check(!out.overflow); return uptr(out.value); } [[nodiscard]] __attribute__((pure)) friend constexpr inline uptr operator/( const uptr& l, const uptr& r) noexcept { ::sus::check(r.primitive_value != 0u); return uptr(__private::unchecked_div(l.primitive_value, r.primitive_value)); } [[nodiscard]] __attribute__((pure)) friend constexpr inline uptr operator%( const uptr& l, const uptr& r) noexcept { ::sus::check(r.primitive_value != 0u); return uptr(__private::unchecked_rem(l.primitive_value, r.primitive_value)); } [[nodiscard]] __attribute__((pure)) friend constexpr inline uptr operator&( const uptr& l, const uptr& r) noexcept { return uptr(__private::unchecked_and(l.primitive_value, r.primitive_value)); } [[nodiscard]] __attribute__((pure)) friend constexpr inline uptr operator|( const uptr& l, const uptr& r) noexcept { return uptr(__private::unchecked_or(l.primitive_value, r.primitive_value)); } [[nodiscard]] __attribute__((pure)) friend constexpr inline uptr operator^( const uptr& l, const uptr& r) noexcept { return uptr(__private::unchecked_xor(l.primitive_value, r.primitive_value)); } [[nodiscard]] __attribute__((pure)) friend constexpr inline uptr operator<<( const uptr& l, const u32& r) noexcept { ::sus::check(r < BITS); return uptr(__private::unchecked_shl(l.primitive_value, r.primitive_value)); } [[nodiscard]] __attribute__((pure)) friend constexpr inline uptr operator>>( const uptr& l, const u32& r) noexcept { ::sus::check(r < BITS); return uptr(__private::unchecked_shr(l.primitive_value, r.primitive_value)); } constexpr inline void operator+=(uptr r) & noexcept { const auto out = __private::add_with_overflow(primitive_value, r.primitive_value); ::sus::check(!out.overflow); primitive_value = out.value; } constexpr inline void operator-=(uptr r) & noexcept { const auto out = __private::sub_with_overflow(primitive_value, r.primitive_value); ::sus::check(!out.overflow); primitive_value = out.value; } constexpr inline void operator*=(uptr r) & noexcept { const auto out = __private::mul_with_overflow(primitive_value, r.primitive_value); ::sus::check(!out.overflow); primitive_value = out.value; } constexpr inline void operator/=(uptr r) & noexcept { ::sus::check(r.primitive_value != 0u); primitive_value /= r.primitive_value; } constexpr inline void operator%=(uptr r) & noexcept { ::sus::check(r.primitive_value != 0u); primitive_value %= r.primitive_value; } constexpr inline void operator&=(uptr r) & noexcept { primitive_value &= r.primitive_value; } constexpr inline void operator|=(uptr r) & noexcept { primitive_value |= r.primitive_value; } constexpr inline void operator^=(uptr r) & noexcept { primitive_value ^= r.primitive_value; } constexpr inline void operator<<=(const u32& r) & noexcept { ::sus::check(r < BITS); primitive_value <<= r.primitive_value; } constexpr inline void operator>>=(const u32& r) & noexcept { ::sus::check(r < BITS); primitive_value >>= r.primitive_value; } __attribute__((pure)) constexpr uptr abs_diff(const uptr& r) const& noexcept { if (primitive_value >= r.primitive_value) return uptr(__private::unchecked_sub(primitive_value, r.primitive_value)); else return uptr(__private::unchecked_sub(r.primitive_value, primitive_value)); } __attribute__((pure)) constexpr ::sus::option::Option<uptr> checked_add( const uptr& rhs) const& noexcept; __attribute__((pure)) constexpr sus::tuple_type::Tuple<uptr, bool> overflowing_add( const uptr& rhs) const& noexcept; __attribute__((pure)) constexpr uptr saturating_add(const uptr& rhs) const& noexcept { return uptr(__private::saturating_add(primitive_value, rhs.primitive_value)); } __attribute__((pure)) inline constexpr uptr unchecked_add( ::sus::marker::UnsafeFnMarker, const uptr& rhs) const& noexcept { return uptr(__private::unchecked_add(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr uptr wrapping_add(const uptr& rhs) const& noexcept { return uptr(__private::wrapping_add(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr ::sus::option::Option<uptr> checked_div( const uptr& rhs) const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<uptr, bool> overflowing_div( const uptr& rhs) const& noexcept; __attribute__((pure)) constexpr uptr saturating_div(const uptr& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return uptr(__private::unchecked_div(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr uptr wrapping_div(const uptr& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return uptr(__private::unchecked_div(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr ::sus::option::Option<uptr> checked_mul( const uptr& rhs) const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<uptr, bool> overflowing_mul( const uptr& rhs) const& noexcept; __attribute__((pure)) constexpr uptr saturating_mul(const uptr& rhs) const& noexcept { return uptr(__private::saturating_mul(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr uptr unchecked_mul(::sus::marker::UnsafeFnMarker, const uptr& rhs) const& noexcept { return uptr(__private::unchecked_mul(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr uptr wrapping_mul(const uptr& rhs) const& noexcept { return uptr(__private::wrapping_mul(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr ::sus::option::Option<uptr> checked_neg() const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<uptr, bool> overflowing_neg() const& noexcept; __attribute__((pure)) constexpr uptr wrapping_neg() const& noexcept { return (uptr(::sus::num::__private::ptr_type<>::unsigned_type{0u})).wrapping_sub(*this); } __attribute__((pure)) constexpr ::sus::option::Option<uptr> checked_rem( const uptr& rhs) const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<uptr, bool> overflowing_rem( const uptr& rhs) const& noexcept; __attribute__((pure)) constexpr uptr wrapping_rem(const uptr& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return uptr(__private::unchecked_rem(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr uptr div_euclid(const uptr& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return uptr(__private::unchecked_div(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr ::sus::option::Option<uptr> checked_div_euclid( const uptr& rhs) const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<uptr, bool> overflowing_div_euclid( const uptr& rhs) const& noexcept; __attribute__((pure)) constexpr uptr wrapping_div_euclid(const uptr& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return uptr(__private::unchecked_div(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr uptr rem_euclid(const uptr& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return uptr(__private::unchecked_rem(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr ::sus::option::Option<uptr> checked_rem_euclid( const uptr& rhs) const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<uptr, bool> overflowing_rem_euclid( const uptr& rhs) const& noexcept; __attribute__((pure)) constexpr uptr wrapping_rem_euclid(const uptr& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return uptr(__private::unchecked_rem(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr ::sus::option::Option<uptr> checked_shl( const u32& rhs) const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<uptr, bool> overflowing_shl( const u32& rhs) const& noexcept; __attribute__((pure)) constexpr uptr wrapping_shl(const u32& rhs) const& noexcept { return uptr( __private::shl_with_overflow(primitive_value, rhs.primitive_value).value); } __attribute__((pure)) constexpr ::sus::option::Option<uptr> checked_shr( const u32& rhs) const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<uptr, bool> overflowing_shr( const u32& rhs) const& noexcept; __attribute__((pure)) constexpr uptr wrapping_shr(const u32& rhs) const& noexcept { return uptr( __private::shr_with_overflow(primitive_value, rhs.primitive_value).value); } __attribute__((pure)) constexpr ::sus::option::Option<uptr> checked_sub( const uptr& rhs) const&; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<uptr, bool> overflowing_sub( const uptr& rhs) const& noexcept; __attribute__((pure)) constexpr uptr saturating_sub(const uptr& rhs) const& { return uptr(__private::saturating_sub(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr uptr unchecked_sub(::sus::marker::UnsafeFnMarker, const uptr& rhs) const& noexcept { return uptr(__private::unchecked_sub(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr uptr wrapping_sub(const uptr& rhs) const& noexcept { return uptr(__private::wrapping_sub(primitive_value, rhs.primitive_value)); } __attribute__((pure)) constexpr u32 count_ones() const& noexcept { return __private::count_ones(primitive_value); } __attribute__((pure)) constexpr u32 count_zeros() const& noexcept { return (~(*this)).count_ones(); } __attribute__((pure)) constexpr u32 leading_ones() const& noexcept { return (~(*this)).leading_zeros(); } __attribute__((pure)) constexpr u32 leading_zeros() const& noexcept { return __private::leading_zeros(primitive_value); } __attribute__((pure)) constexpr u32 trailing_ones() const& noexcept { return (~(*this)).trailing_zeros(); } __attribute__((pure)) constexpr u32 trailing_zeros() const& noexcept { return __private::trailing_zeros(primitive_value); } __attribute__((pure)) constexpr uptr reverse_bits() const& noexcept { return uptr(__private::reverse_bits(primitive_value)); } __attribute__((pure)) constexpr uptr rotate_left(const u32& n) const& noexcept { return uptr(__private::rotate_left(primitive_value, n.primitive_value)); } __attribute__((pure)) constexpr uptr rotate_right(const u32& n) const& noexcept { return uptr(__private::rotate_right(primitive_value, n.primitive_value)); } __attribute__((pure)) constexpr uptr swap_bytes() const& noexcept { return uptr(__private::swap_bytes(primitive_value)); } __attribute__((pure)) constexpr uptr pow(const u32& rhs) const& noexcept { const auto out = __private::pow_with_overflow(primitive_value, rhs.primitive_value); ::sus::check(!out.overflow); return uptr(out.value); } __attribute__((pure)) constexpr ::sus::option::Option<uptr> checked_pow( const u32& rhs) const& noexcept; __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<uptr, bool> overflowing_pow( const u32& exp) const& noexcept; __attribute__((pure)) constexpr uptr wrapping_pow(const u32& exp) const& noexcept { return uptr(__private::wrapping_pow(primitive_value, exp.primitive_value)); } __attribute__((pure)) constexpr ::sus::option::Option<u32> checked_log2() const& noexcept; __attribute__((pure)) constexpr u32 log2() const& noexcept; __attribute__((pure)) constexpr ::sus::option::Option<u32> checked_log10() const& noexcept; __attribute__((pure)) constexpr u32 log10() const& noexcept; __attribute__((pure)) constexpr ::sus::option::Option<u32> checked_log( const uptr& base) const& noexcept; __attribute__((pure)) constexpr u32 log(const uptr& base) const& noexcept; __attribute__((pure)) constexpr bool is_power_of_two() const& noexcept { return count_ones() == uptr(::sus::num::__private::ptr_type<>::unsigned_type{1u}); } __attribute__((pure)) constexpr uptr next_power_of_two() const& noexcept { const auto one_less = __private::one_less_than_next_power_of_two(primitive_value); return uptr(one_less) + uptr(::sus::num::__private::ptr_type<>::unsigned_type{1u}); } __attribute__((pure)) constexpr ::sus::option::Option<uptr> checked_next_power_of_two() const& noexcept; __attribute__((pure)) constexpr uptr wrapping_next_power_of_two() const& noexcept { const auto one_less = __private::one_less_than_next_power_of_two(primitive_value); return uptr(one_less).wrapping_add(uptr(::sus::num::__private::ptr_type<>::unsigned_type{1u})); } [[nodiscard]] __attribute__((pure)) static constexpr uptr from_be(const uptr& x) noexcept { if constexpr (::sus::assertions::is_big_endian()) return x; else return x.swap_bytes(); } [[nodiscard]] __attribute__((pure)) static constexpr uptr from_le(const uptr& x) noexcept { if constexpr (::sus::assertions::is_little_endian()) return x; else return x.swap_bytes(); } __attribute__((pure)) constexpr uptr to_be() const& noexcept { if constexpr (::sus::assertions::is_big_endian()) return *this; else return swap_bytes(); } __attribute__((pure)) constexpr uptr to_le() const& noexcept { if constexpr (::sus::assertions::is_little_endian()) return *this; else return swap_bytes(); } __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of< ::sus::num::__private::ptr_type<>::unsigned_type>()> to_be_bytes() const& noexcept; __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of< ::sus::num::__private::ptr_type<>::unsigned_type>()> to_le_bytes() const& noexcept; __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of< ::sus::num::__private::ptr_type<>::unsigned_type>()> to_ne_bytes() const& noexcept; [[nodiscard]] __attribute__((pure)) static constexpr uptr from_be_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of< ::sus::num::__private::ptr_type<>::unsigned_type>()>& bytes) noexcept; [[nodiscard]] __attribute__((pure)) static constexpr uptr from_le_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of< ::sus::num::__private::ptr_type<>::unsigned_type>()>& bytes) noexcept; [[nodiscard]] __attribute__((pure)) static constexpr uptr from_ne_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of< ::sus::num::__private::ptr_type<>::unsigned_type>()>& bytes) noexcept; __attribute__((pure)) constexpr usize addr() const& noexcept { return static_cast<decltype(std::declval<usize>().primitive_value)>( primitive_value); } }; inline constexpr uptr uptr::MIN = uptr(uptr::MIN_PRIMITIVE); inline constexpr uptr uptr::MAX_BIT_PATTERN = uptr(uptr::MAX_PRIMITIVE); inline constexpr u32 uptr::BITS = u32(__private::num_bits< ::sus::num::__private::ptr_type<>::unsigned_type>()); template <class T> __attribute__((const)) constexpr inline T* operator+(T* t, usize offset) { return t + size_t{offset}; } template <class T> constexpr inline T*& operator+=(T*& t, usize offset) { t += size_t{offset}; return t; } template <class T> __attribute__((const)) constexpr inline T* operator-(T* t, usize offset) { return t - size_t{offset}; } template <class T> constexpr inline T*& operator-=(T*& t, usize offset) { t -= size_t{offset}; return t; } } ::sus::num::u8 inline consteval operator""_u8(unsigned long long val) { if (val > static_cast<unsigned long long>(::sus::num::u8::MAX_PRIMITIVE)) throw "Integer literal out of bounds for ##T##"; return ::sus::num::u8(static_cast<decltype(::sus::num::u8::primitive_value)>(val)); }; ::sus::num::u16 inline consteval operator""_u16(unsigned long long val) { if (val > static_cast<unsigned long long>(::sus::num::u16::MAX_PRIMITIVE)) throw "Integer literal out of bounds for ##T##"; return ::sus::num::u16(static_cast<decltype(::sus::num::u16::primitive_value)>(val)); }; ::sus::num::u32 inline consteval operator""_u32(unsigned long long val) { if (val > static_cast<unsigned long long>(::sus::num::u32::MAX_PRIMITIVE)) throw "Integer literal out of bounds for ##T##"; return ::sus::num::u32(static_cast<decltype(::sus::num::u32::primitive_value)>(val)); }; ::sus::num::u64 inline consteval operator""_u64(unsigned long long val) { if (val > static_cast<unsigned long long>(::sus::num::u64::MAX_PRIMITIVE)) throw "Integer literal out of bounds for ##T##"; return ::sus::num::u64(static_cast<decltype(::sus::num::u64::primitive_value)>(val)); }; ::sus::num::usize inline consteval operator""_usize(unsigned long long val) { if (val > static_cast<unsigned long long>(::sus::num::usize::MAX_PRIMITIVE)) throw "Integer literal out of bounds for ##T##"; return ::sus::num::usize(static_cast<decltype(::sus::num::usize::primitive_value)>(val)); }; namespace sus { using sus::num::u16; using sus::num::u32; using sus::num::u64; using sus::num::u8; using sus::num::uptr; using sus::num::usize; } namespace sus::iter { struct SizeHint { ::sus::num::usize lower; ::sus::option::Option<::sus::num::usize> upper; friend constexpr bool operator==(const SizeHint& lhs, const SizeHint& rhs) noexcept = default; }; } namespace sus::option { namespace __private { template <class T, ::sus::iter::Iterator<Option<T>> Iter> requires ::sus::iter::Product<T> constexpr Option<T> from_product_impl(Iter&& it) noexcept { class IterUntilNone final : public ::sus::iter::IteratorBase<IterUntilNone, T> { public: constexpr IterUntilNone(Iter& iter, bool& found_none) : iter_(iter), found_none_(found_none) {} constexpr Option<T> next() noexcept { Option<Option<T>> next = iter_.next(); Option<T> out; if (next.is_some()) { out = ::sus::move(next).unwrap_unchecked(::sus::marker::unsafe_fn); if (out.is_none()) found_none_ = true; } return out; } constexpr ::sus::iter::SizeHint size_hint() const noexcept { return ::sus::iter::SizeHint(0u, iter_.size_hint().upper); } private: Iter& iter_; bool& found_none_; }; static_assert(::sus::iter::Iterator<IterUntilNone, T>); bool found_none = false; auto out = Option<T>::with(IterUntilNone(it, found_none).product()); if (found_none) out = Option<T>(); return out; } template <class T, ::sus::iter::Iterator<Option<T>> Iter> requires ::sus::iter::Sum<T> constexpr Option<T> from_sum_impl(Iter&& it) noexcept { class IterUntilNone final : public ::sus::iter::IteratorBase<IterUntilNone, T> { public: constexpr IterUntilNone(Iter& iter, bool& found_none) : iter_(iter), found_none_(found_none) {} constexpr Option<T> next() noexcept { Option<Option<T>> next = iter_.next(); Option<T> out; if (next.is_some()) { out = ::sus::move(next).unwrap_unchecked(::sus::marker::unsafe_fn); if (out.is_none()) found_none_ = true; } return out; } constexpr ::sus::iter::SizeHint size_hint() const noexcept { return ::sus::iter::SizeHint(0u, iter_.size_hint().upper); } private: Iter& iter_; bool& found_none_; }; static_assert(::sus::iter::Iterator<IterUntilNone, T>); bool found_none = false; auto out = Option<T>::with(IterUntilNone(it, found_none).sum()); if (found_none) out = Option<T>(); return out; } } } template <class T> struct sus::iter::FromIteratorImpl<::sus::option::Option<T>> { template <class IntoIter, int&..., class Iter = std::decay_t<decltype(std::declval<IntoIter&&>().into_iter())>, class O = typename Iter::Item, class U = ::sus::option::__private::IsOptionType<O>::inner_type> requires(::sus::option::__private::IsOptionType<O>::value && ::sus::iter::IntoIterator<IntoIter, ::sus::option::Option<U>>) static constexpr ::sus::option::Option<T> from_iter( IntoIter&& option_iter) noexcept requires(!std::is_reference_v<T> && ::sus::iter::FromIterator<T, U>) { struct UntilNoneIter final : public ::sus::iter::IteratorBase<UntilNoneIter, U> { UntilNoneIter(Iter&& iter, bool& found_none) : iter(iter), found_none(found_none) {} ::sus::option::Option<U> next() noexcept { ::sus::option::Option<::sus::option::Option<U>> item = iter.next(); if (found_none || item.is_none()) return ::sus::option::Option<U>(); found_none = item->is_none(); return ::sus::move(item).flatten(); } ::sus::iter::SizeHint size_hint() const noexcept { return ::sus::iter::SizeHint(0u, iter.size_hint().upper); } Iter& iter; bool& found_none; }; bool found_none = false; auto iter = UntilNoneIter(::sus::move(option_iter).into_iter(), found_none); auto collected = sus::iter::from_iter<T>(::sus::move(iter)); if (found_none) return ::sus::option::Option<T>(); else return ::sus::option::Option<T>::with(::sus::move(collected)); } }; namespace sus::fn::__private { struct FnBoxStorageVtableBase {}; struct FnBoxStorageBase { virtual ~FnBoxStorageBase() = default; Option<const FnBoxStorageVtableBase&> vtable; }; template <class R, class... CallArgs> struct FnBoxStorageVtable final : public FnBoxStorageVtableBase { R (*call_once)(__private::FnBoxStorageBase&&, CallArgs...); R (*call_mut)(__private::FnBoxStorageBase&, CallArgs...); R (*call)(const __private::FnBoxStorageBase&, CallArgs...); }; template <class F> class FnBoxStorage final : public FnBoxStorageBase { public: ~FnBoxStorage() override = default; constexpr FnBoxStorage(F&& callable) requires(!(std::is_member_function_pointer_v<std::remove_reference_t<F>> || std::is_member_object_pointer_v<std::remove_reference_t<F>>)) : callable_(::sus::move(callable)) {} constexpr FnBoxStorage(F ptr) requires(std::is_member_function_pointer_v<F> || std::is_member_object_pointer_v<F>) : callable_(ptr) {} template <class R, class... CallArgs> static R call(const FnBoxStorageBase& self_base, CallArgs... callargs) { const auto& self = static_cast<const FnBoxStorage&>(self_base); return std::invoke(self.callable_, forward<CallArgs>(callargs)...); } template <class R, class... CallArgs> static R call_mut(FnBoxStorageBase& self_base, CallArgs... callargs) { auto& self = static_cast<FnBoxStorage&>(self_base); return std::invoke(self.callable_, forward<CallArgs>(callargs)...); } template <class R, class... CallArgs> static R call_once(FnBoxStorageBase&& self_base, CallArgs... callargs) { auto&& self = static_cast<FnBoxStorage&&>(self_base); return std::invoke(::sus::move(self.callable_), forward<CallArgs>(callargs)...); } F callable_; }; } namespace sus::fn { template <class R, class... CallArgs> template <::sus::fn::callable::FunctionPointerMatches<R, CallArgs...> F> FnOnceBox<R(CallArgs...)>::FnOnceBox(F ptr) noexcept : fn_ptr_(ptr), type_(__private::FnBoxPointer) { ::sus::check(ptr != nullptr); } template <class R, class... CallArgs> template <class ConstructionType, ::sus::fn::callable::CallableObjectReturnsOnce<R, CallArgs...> F> requires(!(std::is_member_function_pointer_v<std::remove_reference_t<F>> || std::is_member_object_pointer_v<std::remove_reference_t<F>>)) FnOnceBox<R(CallArgs...)>::FnOnceBox(ConstructionType construction, F&& lambda) noexcept : type_(__private::Storage) { auto* s = new __private::FnBoxStorage<F>(::sus::move(lambda)); make_vtable(*s, construction); storage_ = s; } template <class R, class... CallArgs> template <class ConstructionType, ::sus::fn::callable::CallableObjectReturnsOnce<R, CallArgs...> F> requires(std::is_member_function_pointer_v<F> || std::is_member_object_pointer_v<F>) FnOnceBox<R(CallArgs...)>::FnOnceBox(ConstructionType construction, F ptr) noexcept : type_(__private::Storage) { ::sus::check(ptr != nullptr); auto* s = new __private::FnBoxStorage<F>(ptr); make_vtable(*s, construction); storage_ = s; } template <class R, class... CallArgs> template <class FnBoxStorage> void FnOnceBox<R(CallArgs...)>::make_vtable( FnBoxStorage& storage, __private::StorageConstructionFnOnceBoxType) noexcept { static __private::FnBoxStorageVtable<R, CallArgs...> vtable = { .call_once = &FnBoxStorage::template call_once<R, CallArgs...>, .call_mut = nullptr, .call = nullptr, }; storage.vtable.insert(vtable); } template <class R, class... CallArgs> template <class FnBoxStorage> void FnOnceBox<R(CallArgs...)>::make_vtable( FnBoxStorage& storage, __private::StorageConstructionFnMutBoxType) noexcept { static __private::FnBoxStorageVtable<R, CallArgs...> vtable = { .call_once = &FnBoxStorage::template call_once<R, CallArgs...>, .call_mut = &FnBoxStorage::template call_mut<R, CallArgs...>, .call = nullptr, }; storage.vtable.insert(vtable); } template <class R, class... CallArgs> template <class FnBoxStorage> void FnOnceBox<R(CallArgs...)>::make_vtable( FnBoxStorage& storage, __private::StorageConstructionFnBoxType) noexcept { static __private::FnBoxStorageVtable<R, CallArgs...> vtable = { .call_once = &FnBoxStorage::template call_once<R, CallArgs...>, .call_mut = &FnBoxStorage::template call_mut<R, CallArgs...>, .call = &FnBoxStorage::template call<R, CallArgs...>, }; storage.vtable.insert(vtable); } template <class R, class... CallArgs> FnOnceBox<R(CallArgs...)>::~FnOnceBox() noexcept { switch (type_) { case __private::FnBoxPointer: break; case __private::Storage: { if (auto* s = ::sus::mem::replace(storage_, nullptr); s) delete s; break; } } } template <class R, class... CallArgs> FnOnceBox<R(CallArgs...)>::FnOnceBox(FnOnceBox&& o) noexcept : type_(o.type_) { switch (type_) { case __private::FnBoxPointer: ::sus::check(o.fn_ptr_); fn_ptr_ = ::sus::mem::replace(o.fn_ptr_, nullptr); break; case __private::Storage: ::sus::check(o.storage_); storage_ = ::sus::mem::replace(o.storage_, nullptr); break; } } template <class R, class... CallArgs> FnOnceBox<R(CallArgs...)>& FnOnceBox<R(CallArgs...)>::operator=( FnOnceBox&& o) noexcept { switch (type_) { case __private::FnBoxPointer: break; case __private::Storage: if (auto* s = ::sus::mem::replace(storage_, nullptr); s) delete s; } switch (type_ = o.type_) { case __private::FnBoxPointer: ::sus::check(o.fn_ptr_); fn_ptr_ = ::sus::mem::replace(o.fn_ptr_, nullptr); break; case __private::Storage: ::sus::check(o.storage_); storage_ = ::sus::mem::replace(o.storage_, nullptr); break; } return *this; } template <class R, class... CallArgs> R FnOnceBox<R(CallArgs...)>::operator()(CallArgs... args) && noexcept { switch (type_) { case __private::FnBoxPointer: { ::sus::check(fn_ptr_); auto* fn = ::sus::mem::replace(fn_ptr_, nullptr); return std::invoke(fn, static_cast<CallArgs&&>(args)...); } case __private::Storage: { ::sus::check(storage_); auto* storage = ::sus::mem::replace(storage_, nullptr); auto& vtable = static_cast<const __private::FnBoxStorageVtable<R, CallArgs...>&>( storage->vtable.as_mut().unwrap()); struct DeleteStorage final { constexpr inline DeleteStorage(__private::FnBoxStorageBase* storage) : storage(storage){}; ~DeleteStorage() { delete storage; } __private::FnBoxStorageBase* storage; } deleter(storage); return vtable.call_once( static_cast<__private::FnBoxStorageBase&&>(*storage), forward<CallArgs>(args)...); } } ::sus::unreachable_unchecked(::sus::marker::unsafe_fn); } template <class R, class... CallArgs> R FnMutBox<R(CallArgs...)>::operator()(CallArgs... args) & noexcept { using Super = FnOnceBox<R(CallArgs...)>; switch (Super::type_) { case __private::FnBoxPointer: ::sus::check(Super::fn_ptr_); return Super::fn_ptr_(static_cast<CallArgs&&>(args)...); case __private::Storage: { ::sus::check(Super::storage_); auto& vtable = static_cast<const __private::FnBoxStorageVtable<R, CallArgs...>&>( Super::storage_->vtable.as_mut().unwrap()); return vtable.call_mut( static_cast<__private::FnBoxStorageBase&>(*Super::storage_), ::sus::forward<CallArgs>(args)...); } } ::sus::unreachable_unchecked(::sus::marker::unsafe_fn); } template <class R, class... CallArgs> R FnBox<R(CallArgs...)>::operator()(CallArgs... args) const& noexcept { using Super = FnOnceBox<R(CallArgs...)>; switch (Super::type_) { case __private::FnBoxPointer: ::sus::check(Super::fn_ptr_); return Super::fn_ptr_(static_cast<CallArgs&&>(args)...); case __private::Storage: { ::sus::check(Super::storage_); auto& vtable = static_cast<const __private::FnBoxStorageVtable<R, CallArgs...>&>( Super::storage_->vtable.as_mut().unwrap()); return vtable.call( static_cast<const __private::FnBoxStorageBase&>(*Super::storage_), ::sus::forward<CallArgs>(args)...); } } ::sus::unreachable_unchecked(::sus::marker::unsafe_fn); } } namespace sus::iter::__private { template <class T> struct IsGenerator; template <class T> struct IsGenerator final : std::false_type { using type = void; }; template <class T> struct IsGenerator<Generator<T>> final : std::true_type { using type = T; }; } namespace sus::iter::__private { template <class Ordering, class ItemA, class ItemB> constexpr inline Ordering iter_compare( ::sus::iter::Iterator<ItemA> auto&& a, ::sus::iter::Iterator<ItemB> auto&& b, ::sus::fn::FnMut<Ordering(const std::remove_reference_t<ItemA>&, const std::remove_reference_t<ItemB>&)> auto&& f) requires(sus::mem::IsMoveRef<decltype(f)>) { Ordering value = Ordering::equivalent; while (true) { ::sus::Option<ItemA> item_a = a.next(); ::sus::Option<ItemB> item_b = b.next(); if (item_a.is_none() && item_b.is_none()) { return value; } else if (item_a.is_none()) { value = Ordering::less; return value; } else if (item_b.is_none()) { value = Ordering::greater; return value; } else { value = ::sus::fn::call_mut(f, item_a.as_value(), item_b.as_value()); if (!(value == 0)) return value; } } } template <class ItemA, class ItemB> constexpr inline bool iter_compare_eq( ::sus::iter::Iterator<ItemA> auto&& a, ::sus::iter::Iterator<ItemB> auto&& b, ::sus::fn::FnMut<bool(const std::remove_reference_t<ItemA>&, const std::remove_reference_t<ItemB>&)> auto&& f) requires(sus::mem::IsMoveRef<decltype(f)>) { bool value = true; while (true) { ::sus::Option<ItemA> item_a = a.next(); ::sus::Option<ItemB> item_b = b.next(); if (item_a.is_none() && item_b.is_none()) { return value; } else if (item_a.is_none()) { value = false; return value; } else if (item_b.is_none()) { value = false; return value; } else { value = ::sus::fn::call_mut(f, item_a.as_value(), item_b.as_value()); if (!value) return value; } } } } namespace sus::iter::__private { struct IteratorEnd {}; } namespace sus::iter::__private { template <class Iter> class [[nodiscard]] IteratorLoop final { using Item = typename std::remove_reference_t<Iter>::Item; public: constexpr IteratorLoop(Iter&& iter) noexcept : iter_(::sus::forward<Iter>(iter)), item_(iter_.next()) {} constexpr inline bool operator==(__private::IteratorEnd) const noexcept { return item_.is_none(); } constexpr inline void operator++() & noexcept { item_ = iter_.next(); } constexpr inline Item operator*() & noexcept { return item_.take().unwrap_unchecked(::sus::marker::unsafe_fn); } private: Iter iter_; Option<Item> item_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(iter_), decltype(item_)>; }; template <class T> requires requires(const T& t) { { t.iter() }; } constexpr auto begin(const T& t) noexcept { return IteratorLoop(t.iter()); } template <class T> requires requires(const T& t) { { t.iter() }; } constexpr auto end(const T&) noexcept { return ::sus::iter::__private::IteratorEnd(); } } namespace sus::iter { template <class Collection, class ItemType> concept Extend = requires(Collection c, __private::IntoIteratorArchetype<ItemType>&& iter) { { c.extend(::sus::move(iter)) } -> std::same_as<void>; }; } namespace sus::choice_type::__private { template <class... Ts> struct PackFirstHelper; template <class T, class... Ts> struct PackFirstHelper<T, Ts...> { using type = T; }; template <class... Ts> using PackFirst = PackFirstHelper<Ts...>::type; template <size_t I, class... Ts> struct PackIthHelper; template <size_t I, class T, class... Ts> struct PackIthHelper<I, T, Ts...> { using type = PackIthHelper<I - 1, Ts...>::type; }; template <class T, class... Ts> struct PackIthHelper<0, T, Ts...> { using type = T; }; template <size_t I, class... Ts> using PackIth = PackIthHelper<I, Ts...>::type; } namespace sus::num { template <class Rhs, class Output = Rhs> concept Neg = requires(Rhs rhs) { { -static_cast<Rhs&&>(rhs) } -> std::same_as<Output>; }; template <class Rhs, class Output = Rhs> concept BitNot = requires(Rhs rhs) { { ~static_cast<Rhs&&>(rhs) } -> std::same_as<Output>; }; template <class Lhs, class Rhs, class Output = Lhs> concept Add = requires(const Lhs& lhs, const Rhs& rhs) { { lhs + rhs } -> std::same_as<Output>; }; template <class Lhs, class Rhs> concept AddAssign = requires(Lhs& lhs, const Rhs& rhs) { { lhs += rhs } -> std::same_as<void>; }; template <class Lhs, class Rhs, class Output = Lhs> concept Sub = requires(const Lhs& lhs, const Rhs& rhs) { { lhs - rhs } -> std::same_as<Output>; }; template <class Lhs, class Rhs> concept SubAssign = requires(Lhs& lhs, const Rhs& rhs) { { lhs -= rhs } -> std::same_as<void>; }; template <class Lhs, class Rhs, class Output = Lhs> concept Mul = requires(const Lhs& lhs, const Rhs& rhs) { { lhs* rhs } -> std::same_as<Output>; }; template <class Lhs, class Rhs> concept MulAssign = requires(Lhs& lhs, const Rhs& rhs) { { lhs *= rhs } -> std::same_as<void>; }; template <class Lhs, class Rhs, class Output = Lhs> concept Div = requires(const Lhs& lhs, const Rhs& rhs) { { lhs / rhs } -> std::same_as<Output>; }; template <class Lhs, class Rhs> concept DivAssign = requires(Lhs& lhs, const Rhs& rhs) { { lhs /= rhs } -> std::same_as<void>; }; template <class Lhs, class Rhs, class Output = Lhs> concept Rem = requires(const Lhs& lhs, const Rhs& rhs) { { lhs % rhs } -> std::same_as<Output>; }; template <class Lhs, class Rhs> concept RemAssign = requires(Lhs& lhs, const Rhs& rhs) { { lhs %= rhs } -> std::same_as<void>; }; template <class Lhs, class Rhs, class Output = Lhs> concept BitAnd = requires(const Lhs& lhs, const Rhs& rhs) { { lhs& rhs } -> std::same_as<Output>; }; template <class Lhs, class Rhs> concept BitAndAssign = requires(Lhs& lhs, const Rhs& rhs) { { lhs &= rhs } -> std::same_as<void>; }; template <class Lhs, class Rhs, class Output = Lhs> concept BitOr = requires(const Lhs& lhs, const Rhs& rhs) { { lhs | rhs } -> std::same_as<Output>; }; template <class Lhs, class Rhs> concept BitOrAssign = requires(Lhs& lhs, const Rhs& rhs) { { lhs |= rhs } -> std::same_as<void>; }; template <class Lhs, class Rhs, class Output = Lhs> concept BitXor = requires(const Lhs& lhs, const Rhs& rhs) { { lhs ^ rhs } -> std::same_as<Output>; }; template <class Lhs, class Rhs> concept BitXorAssign = requires(Lhs& lhs, const Rhs& rhs) { { lhs ^= rhs } -> std::same_as<void>; }; template <class Lhs, class Output = Lhs> concept Shl = requires(const Lhs& lhs ) { { lhs << 2u } -> std::same_as<Output>; }; template <class Lhs> concept ShlAssign = requires(Lhs& lhs ) { { lhs <<= 2u } -> std::same_as<void>; }; template <class Lhs, class Output = Lhs> concept Shr = requires(const Lhs& lhs ) { { lhs >> 2u } -> std::same_as<Output>; }; template <class Lhs> concept ShrAssign = requires(Lhs& lhs ) { { lhs >>= 2u } -> std::same_as<void>; }; } namespace sus::tuple_type::__private { template <class... T> struct TupleStorage; template <class T> struct TupleStorage<T> { TupleStorage() requires(std::is_trivially_default_constructible_v<T>) = default; template <class U> constexpr inline explicit TupleStorage(U&& value) : value(::sus::forward<U>(value)) {} inline constexpr const T& at() const& noexcept { return value; } inline constexpr T& at_mut() & noexcept { return value; } inline constexpr T&& into_inner() && noexcept { return ::sus::move(value); } private: [[no_unique_address]] T value; }; template <class T> struct TupleStorage<T&> { constexpr inline explicit TupleStorage(T& value) : value(::sus::mem::addressof(value)) {} inline constexpr const T& at() const& noexcept { return *value; } inline constexpr T& at_mut() & noexcept { return *value; } inline constexpr T& into_inner() && noexcept { return *value; } private: T* value; }; template <class T, class... Ts> requires(sizeof...(Ts) > 0) struct TupleStorage<T, Ts...> : TupleStorage<Ts...> { using Super = TupleStorage<Ts...>; TupleStorage() requires(std::is_trivially_default_constructible_v<T>) = default; template <class U, class... Us> constexpr inline TupleStorage(U&& value, Us&&... more) noexcept : Super(::sus::forward<Us>(more)...), value(::sus::forward<U>(value)) {} inline constexpr const T& at() const& noexcept { return value; } inline constexpr T& at_mut() & noexcept { return value; } inline constexpr T&& into_inner() && noexcept { return ::sus::move(value); } private: [[no_unique_address]] T value; }; template <class T, class... Ts> requires(sizeof...(Ts) > 0) struct TupleStorage<T&, Ts...> : TupleStorage<Ts...> { using Super = TupleStorage<Ts...>; template <class... Us> constexpr inline TupleStorage(T& value, Us&&... more) noexcept : Super(::sus::forward<Us>(more)...), value(::sus::mem::addressof(value)) {} inline constexpr const T& at() const& noexcept { return *value; } inline constexpr T& at_mut() & noexcept { return *value; } inline constexpr T& into_inner() && noexcept { return *value; } private: T* value; }; template <size_t I, class S> static constexpr const auto& find_tuple_storage(const S& storage) { return find_tuple_storage(storage, std::integral_constant<size_t, I>()); } template <size_t I, class S> static constexpr const auto& find_tuple_storage( const S& storage, std::integral_constant<size_t, I>) { return find_tuple_storage(static_cast<const S::Super&>(storage), std::integral_constant<size_t, I - 1>()); } template <class S> static constexpr const S& find_tuple_storage( const S& storage, std::integral_constant<size_t, 0>) { return storage; } template <size_t I, class S> static constexpr auto& find_tuple_storage_mut(S& storage) { return find_tuple_storage_mut(storage, std::integral_constant<size_t, I>()); } template <size_t I, class S> static constexpr auto& find_tuple_storage_mut( S& storage, std::integral_constant<size_t, I>) { return find_tuple_storage_mut(static_cast<S::Super&>(storage), std::integral_constant<size_t, I - 1>()); } template <class S> static constexpr S& find_tuple_storage_mut(S& storage, std::integral_constant<size_t, 0>) { return storage; } template <size_t I, class S1, class S2> constexpr inline auto storage_eq_impl(const S1& l, const S2& r) noexcept { return find_tuple_storage<I>(l).at() == find_tuple_storage<I>(r).at(); }; template <class S1, class S2, size_t... N> constexpr inline auto storage_eq(const S1& l, const S2& r, std::index_sequence<N...>) noexcept { return (... && (storage_eq_impl<N>(l, r))); }; template <size_t I, class O, class S1, class S2> constexpr inline bool storage_cmp_impl(O& val, const S1& l, const S2& r) noexcept { auto cmp = find_tuple_storage<I>(l).at() <=> find_tuple_storage<I>(r).at(); if (cmp != 0) val = cmp; return val == 0; }; template <class S1, class S2, size_t... N> constexpr inline auto storage_cmp(auto equal, const S1& l, const S2& r, std::index_sequence<N...>) noexcept { auto val = equal; (... && (storage_cmp_impl<N>(val, l, r))); return val; }; } namespace sus::tuple_type { template <class T, class... Ts> class Tuple final { public: explicit inline constexpr Tuple() noexcept requires(!((std::is_trivially_default_constructible_v<T> && ... && std::is_trivially_default_constructible_v<Ts>) && !(std::is_reference_v<T> || ... || std::is_reference_v<Ts>) ) && (::sus::construct::Default<T> && ... && ::sus::construct::Default<Ts>)) : Tuple(T(), Ts()...) {} explicit Tuple() requires((std::is_trivially_default_constructible_v<T> && ... && std::is_trivially_default_constructible_v<Ts>) && !(std::is_reference_v<T> || ... || std::is_reference_v<Ts>)) = default; template <std::convertible_to<T> U, std::convertible_to<Ts>... Us> requires(sizeof...(Us) == sizeof...(Ts) && (sus::construct::SafelyConstructibleFromReference<T, U &&> && ... && sus::construct::SafelyConstructibleFromReference<Ts, Us &&>)) constexpr inline static Tuple with(U&& first, Us&&... more) noexcept { return Tuple(::sus::forward<U>(first), ::sus::forward<Us>(more)...); } constexpr Tuple clone() const& noexcept requires((::sus::mem::CloneOrRef<T> && ... && ::sus::mem::CloneOrRef<Ts>) && !(::sus::mem::CopyOrRef<T> && ... && ::sus::mem::CopyOrRef<Ts>)) { auto f = [this]<size_t... Is>(std::index_sequence<Is...>) { return Tuple::with(::sus::mem::clone_or_forward<T>( __private::find_tuple_storage<Is>(storage_).at())...); }; return f(std::make_index_sequence<1u + sizeof...(Ts)>()); } template <size_t I> requires(I <= sizeof...(Ts)) constexpr inline const auto& at() const& noexcept { return __private::find_tuple_storage<I>(storage_).at(); } template <size_t I> constexpr inline const auto& at() && = delete; template <size_t I> requires(I <= sizeof...(Ts)) constexpr inline auto& at_mut() & noexcept { return __private::find_tuple_storage_mut<I>(storage_).at_mut(); } template <size_t I> requires(I <= sizeof...(Ts)) constexpr inline decltype(auto) into_inner() && noexcept { return ::sus::move(__private::find_tuple_storage_mut<I>(storage_)) .into_inner(); } constexpr bool operator==(const Tuple& r) const& noexcept requires((::sus::ops::Eq<T> && ... && ::sus::ops::Eq<Ts>)) { return __private::storage_eq( storage_, r.storage_, std::make_index_sequence<1u + sizeof...(Ts)>()); } template <class U, class... Us> requires(sizeof...(Us) == sizeof...(Ts) && (::sus::ops::Eq<T, U> && ... && ::sus::ops::Eq<Ts, Us>)) constexpr bool operator==(const Tuple<U, Us...>& r) const& noexcept { return __private::storage_eq( storage_, r.storage_, std::make_index_sequence<1u + sizeof...(Ts)>()); } constexpr auto operator<=>(const Tuple& r) const& noexcept requires((::sus::ops::ExclusiveOrd<T> && ... && ::sus::ops::ExclusiveOrd<Ts>)) { return __private::storage_cmp( std::strong_ordering::equal, storage_, r.storage_, std::make_index_sequence<1u + sizeof...(Ts)>()); } template <class U, class... Us> requires(sizeof...(Us) == sizeof...(Ts) && (::sus::ops::ExclusiveOrd<T, U> && ... && ::sus::ops::ExclusiveOrd<Ts, Us>)) constexpr auto operator<=>(const Tuple<U, Us...>& r) const& noexcept { return __private::storage_cmp( std::strong_ordering::equal, storage_, r.storage_, std::make_index_sequence<1u + sizeof...(Ts)>()); } constexpr auto operator<=>(const Tuple& r) const& noexcept requires((::sus::ops::ExclusiveWeakOrd<T> && ... && ::sus::ops::ExclusiveWeakOrd<Ts>)) { return __private::storage_cmp( std::weak_ordering::equivalent, storage_, r.storage_, std::make_index_sequence<1u + sizeof...(Ts)>()); } template <class U, class... Us> requires(sizeof...(Us) == sizeof...(Ts) && (::sus::ops::ExclusiveWeakOrd<T, U> && ... && ::sus::ops::ExclusiveWeakOrd<Ts, Us>)) constexpr auto operator<=>(const Tuple<U, Us...>& r) const& noexcept { return __private::storage_cmp( std::weak_ordering::equivalent, storage_, r.storage_, std::make_index_sequence<1u + sizeof...(Ts)>()); } constexpr auto operator<=>(const Tuple& r) const& noexcept requires((::sus::ops::ExclusivePartialOrd<T> && ... && ::sus::ops::ExclusivePartialOrd<Ts>)) { return __private::storage_cmp( std::partial_ordering::equivalent, storage_, r.storage_, std::make_index_sequence<1u + sizeof...(Ts)>()); } template <class U, class... Us> requires(sizeof...(Us) == sizeof...(Ts) && (::sus::ops::ExclusivePartialOrd<T, U> && ... && ::sus::ops::ExclusivePartialOrd<Ts, Us>)) constexpr auto operator<=>(const Tuple<U, Us...>& r) const& noexcept { return __private::storage_cmp( std::partial_ordering::equivalent, storage_, r.storage_, std::make_index_sequence<1u + sizeof...(Ts)>()); } template <class U, class... Us> requires(sizeof...(Us) == sizeof...(Ts) && (::sus::iter::Extend<T, U> && ... && ::sus::iter::Extend<Ts, Us>)) constexpr void extend( ::sus::iter::IntoIterator<Tuple<U, Us...>> auto&& ii) noexcept requires(::sus::mem::IsMoveRef<decltype(ii)>) { for (Tuple<U, Us...>&& item : ::sus::move(ii).into_iter()) { auto f = [this]<size_t... Is>(Tuple<U, Us...>&& item, std::index_sequence<Is...>) mutable { using Items = Tuple<U, Us...>; (..., at_mut<Is>().extend( ::sus::option::Option<typename Items::template IthType<Is>>::with( ::sus::move(item).template into_inner<Is>()))); }; f(::sus::move(item), std::make_index_sequence<1u + sizeof...(Ts)>()); } } private: template <class U, class... Us> friend class Tuple; using Storage = __private::TupleStorage<T, Ts...>; template <size_t I> using IthType = ::sus::choice_type::__private::PackIth<I, T, Ts...>; template <std::convertible_to<T> U, std::convertible_to<Ts>... Us> constexpr inline Tuple(U&& first, Us&&... more) noexcept : storage_(::sus::forward<U>(first), ::sus::forward<Us>(more)...) {} [[no_unique_address]] Storage storage_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<T, Ts...>; }; template <size_t I, class... Ts> constexpr decltype(auto) get(const Tuple<Ts...>& t) noexcept { return t.template at<I>(); } template <size_t I, class... Ts> constexpr decltype(auto) get(Tuple<Ts...>& t) noexcept { return t.template at_mut<I>(); } template <size_t I, class... Ts> constexpr decltype(auto) get(Tuple<Ts...>&& t) noexcept { return static_cast<decltype(::sus::move(t).template into_inner<I>())>( t.template at_mut<I>()); } namespace __private { template <class... Ts> struct TupleMarker { constexpr inline TupleMarker(Tuple<Ts&&...>&& values) : values(::sus::move(values)){}; Tuple<Ts&&...> values; template <class... Us> requires((... && std::constructible_from<Us, std::remove_reference_t<Ts>&>)) __attribute__((pure)) inline constexpr operator Tuple<Us...>() const& noexcept { static_assert( (... && ::sus::construct::SafelyConstructibleFromReference<Us, const Ts&>), "Unable to safely convert to a different reference type, as conversion " "would produce a reference to a temporary. The TupleMarker's value " "type must match the Tuple's. For example a `Tuple<const i32&, u32>` " "can not be constructed from a TupleMarker holding `const i16&, u32`, " "but it can be constructed from `i32&&, u16`."); auto make_tuple = [this]<size_t... Is>(std::integer_sequence<size_t, Is...>) { return Tuple<Us...>::with(values.template at<Is>()...); }; return make_tuple(std::make_integer_sequence<size_t, sizeof...(Ts)>()); } template <class... Us> inline constexpr operator Tuple<Us...>() && noexcept { static_assert( (... && ::sus::construct::SafelyConstructibleFromReference<Us, Ts&&>), "Unable to safely convert to a different reference type, as conversion " "would produce a reference to a temporary. The TupleMarker's value " "type must match the Tuple's. For example a `Tuple<const i32&, u32>` " "can not be constructed from a TupleMarker holding `const i16&, u32`, " "but it can be constructed from `i32&&, u16`."); auto make_tuple = [this]<size_t... Is>(std::integer_sequence<size_t, Is...>) { return Tuple<Us...>::with( ::sus::forward<Ts>(values.template at_mut<Is>())...); }; return make_tuple(std::make_integer_sequence<size_t, sizeof...(Ts)>()); } inline constexpr Tuple<Ts...> construct() && noexcept { return ::sus::move(*this); } template <class... Us> inline constexpr Tuple<Us...> construct() && noexcept { return ::sus::move(*this); } }; } template <class... Ts> requires(sizeof...(Ts) > 0) [[nodiscard]] inline constexpr auto tuple( Ts&&... vs) noexcept { return __private::TupleMarker<Ts...>( ::sus::tuple_type::Tuple<Ts&&...>::with(::sus::forward<Ts>(vs)...)); } } namespace std { template <class... Types> struct tuple_size<::sus::tuple_type::Tuple<Types...>> { static constexpr size_t value = sizeof...(Types); }; template <size_t I, class T, class... Types> struct tuple_element<I, ::sus::tuple_type::Tuple<T, Types...>> { using type = tuple_element<I - 1, ::sus::tuple_type::Tuple<Types...>>::type; }; template <class T, class... Types> struct tuple_element<0, ::sus::tuple_type::Tuple<T, Types...>> { using type = T; }; } namespace sus { using ::sus::tuple_type::Tuple; using ::sus::tuple_type::tuple; } namespace sus::iter { using ::sus::construct::Into; using ::sus::option::Option; template <class Iter, class ItemT> class IteratorBase { protected: constexpr IteratorBase() noexcept { static_assert(std::same_as<ItemT, typename Iter::Item>); static_assert(std::is_final_v<Iter>, "Iterator implementations must be `final`, as the provided " "methods must know the complete type."); } constexpr inline const Iter& as_subclass() const { return static_cast<const Iter&>(*this); } constexpr inline Iter& as_subclass_mut() { return static_cast<Iter&>(*this); } public: using Item = ItemT; constexpr auto begin() & noexcept { return __private::IteratorLoop<Iter&>(as_subclass_mut()); } constexpr auto end() & noexcept { return __private::IteratorEnd(); } constexpr Iter&& into_iter() && noexcept { return static_cast<Iter&&>(*this); } constexpr bool all(::sus::fn::FnMut<bool(Item)> auto f) noexcept; constexpr bool any(::sus::fn::FnMut<bool(Item)> auto f) noexcept; constexpr Iterator<Item> auto by_ref() & noexcept; template <IntoIterator<ItemT> Other> constexpr Iterator<Item> auto chain(Other&& other) && noexcept; Iterator<std::remove_cvref_t<Item>> auto cloned() && noexcept requires(::sus::mem::Clone<Item>); template <IntoIteratorAny Other, int&..., class OtherItem = typename IntoIteratorOutputType<Other>::Item> requires(::sus::ops::Ord<ItemT, OtherItem>) std::strong_ordering cmp(Other&& other) && noexcept; template <IntoIteratorAny Other, int&..., class OtherItem = typename IntoIteratorOutputType<Other>::Item> std::strong_ordering cmp_by(Other&& other, ::sus::fn::FnMutBox<std::strong_ordering( const std::remove_reference_t<Item>&, const std::remove_reference_t<OtherItem>&)> cmp) && noexcept; Iterator<std::remove_cvref_t<Item>> auto copied() && noexcept requires(::sus::mem::Copy<Item>); constexpr ::sus::num::usize count() && noexcept; constexpr Iterator<Item> auto cycle() && noexcept requires(::sus::mem::Clone<Iter>); constexpr auto enumerate() && noexcept; template <IntoIteratorAny Other, int&..., class OtherItem = typename IntoIteratorOutputType<Other>::Item> requires(::sus::ops::Eq<ItemT, OtherItem>) constexpr bool eq(Other&& other) && noexcept; template <IntoIteratorAny Other, int&..., class OtherItem = typename IntoIteratorOutputType<Other>::Item> constexpr bool eq_by( Other&& other, ::sus::fn::FnMut<bool(const std::remove_reference_t<Item>&, const std::remove_reference_t<OtherItem>&)> auto eq_fn) && noexcept; constexpr Iterator<Item> auto filter( ::sus::fn::FnMut<bool(const std::remove_reference_t<Item>&)> auto pred) && noexcept; template < ::sus::fn::FnMut<::sus::fn::NonVoid(ItemT&&)> MapFn, int&..., class R = std::invoke_result_t<MapFn&, ItemT&&>, class InnerR = ::sus::option::__private::IsOptionType<R>::inner_type> requires(::sus::option::__private::IsOptionType<R>::value) constexpr Iterator<InnerR> auto filter_map(MapFn f) && noexcept; constexpr Option<Item> find( ::sus::fn::FnMut<bool(const std::remove_reference_t<Item>&)> auto pred) noexcept; template < ::sus::fn::FnMut<::sus::fn::NonVoid(ItemT&&)> FindFn, int&..., class R = std::invoke_result_t<FindFn&, ItemT&&>, class InnerR = ::sus::option::__private::IsOptionType<R>::inner_type> requires(::sus::option::__private::IsOptionType<R>::value) constexpr Option<InnerR> find_map(FindFn f) noexcept; template <::sus::fn::FnMut<::sus::fn::NonVoid(ItemT&&)> F, int&..., class R = std::invoke_result_t<F&, ItemT&&>, class InnerR = IntoIteratorOutputType<R>::Item> requires(IntoIteratorAny<R>) constexpr Iterator<InnerR> auto flat_map(F f) && noexcept; constexpr auto flatten() && noexcept requires(IntoIteratorAny<Item>); template <class B, ::sus::fn::FnMut<::sus::fn::NonVoid(B, ItemT)> F> requires(std::convertible_to<std::invoke_result_t<F&, B &&, ItemT &&>, B> && (!std::is_reference_v<B> || std::is_reference_v<std::invoke_result_t<F&, B &&, ItemT &&>>)) constexpr B fold(B init, F f) && noexcept; template <::sus::fn::FnMut<void(ItemT&&)> F> constexpr void for_each(F f) && noexcept; constexpr Iterator<Item> auto fuse() && noexcept; template <::sus::fn::FnOnce<::sus::fn::NonVoid(Iter&&)> GenFn, int&..., class R = std::invoke_result_t<GenFn&&, Iter&&>, class GenR = __private::IsGenerator<R>::type> requires(__private::IsGenerator<R>::value) Iterator<GenR> auto generate(GenFn generator_fn) && noexcept; template <IntoIteratorAny Other, int&..., class OtherItem = typename IntoIteratorOutputType<Other>::Item> requires(::sus::ops::PartialOrd<ItemT, OtherItem>) constexpr bool ge(Other&& other) && noexcept; template <IntoIteratorAny Other, int&..., class OtherItem = typename IntoIteratorOutputType<Other>::Item> requires(::sus::ops::PartialOrd<ItemT, OtherItem>) constexpr bool gt(Other&& other) && noexcept; constexpr Iterator<Item> auto inspect( ::sus::fn::FnMut<void(const std::remove_reference_t<Item>&)> auto fn) && noexcept; constexpr bool is_sorted() noexcept requires(::sus::ops::Ord<Item>); constexpr bool is_sorted_by( ::sus::fn::FnMut<std::strong_ordering( const std::remove_reference_t<Item>&, const std::remove_reference_t<Item>&)> auto compare) noexcept; template <IntoIteratorAny Other, int&..., class OtherItem = typename IntoIteratorOutputType<Other>::Item> requires(::sus::ops::PartialOrd<ItemT, OtherItem>) constexpr bool le(Other&& other) && noexcept; template <IntoIteratorAny Other, int&..., class OtherItem = typename IntoIteratorOutputType<Other>::Item> requires(::sus::ops::PartialOrd<ItemT, OtherItem>) constexpr bool lt(Other&& other) && noexcept; constexpr Option<Item> last() && noexcept; template <class T, int&..., class R = std::invoke_result_t<T, Item&&>, class B = ::sus::fn::FnMutBox<R(Item&&)>> requires(!std::is_void_v<R> && Into<T, B>) Iterator<R> auto map(T fn) && noexcept; template < class F, int&..., class R = std::invoke_result_t<F&, Item&&>, class InnerR = ::sus::option::__private::IsOptionType<R>::inner_type, class B = ::sus::fn::FnMutBox<R(Item&&)>> requires(::sus::option::__private::IsOptionType<R>::value && Into<F, B>) Iterator<InnerR> auto map_while(F fn) && noexcept; Option<Item> max() && noexcept requires(::sus::ops::Ord<Item>); Option<Item> max_by(sus::fn::FnMutRef<std::strong_ordering( const std::remove_reference_t<Item>&, const std::remove_reference_t<Item>&)> compare) && noexcept; template <::sus::fn::FnMut< ::sus::fn::NonVoid(const std::remove_reference_t<ItemT>&)> KeyFn, int&..., class Key = std::invoke_result_t< KeyFn&, const std::remove_reference_t<ItemT>&>> requires(::sus::ops::Ord<Key> && !std::is_reference_v<Key>) Option<Item> max_by_key(KeyFn fn) && noexcept; Option<Item> min() && noexcept requires(::sus::ops::Ord<Item>); Option<Item> min_by(sus::fn::FnMutRef<std::strong_ordering( const std::remove_reference_t<Item>&, const std::remove_reference_t<Item>&)> compare) && noexcept; template <::sus::fn::FnMut< ::sus::fn::NonVoid(const std::remove_reference_t<ItemT>&)> KeyFn, int&..., class Key = std::invoke_result_t< KeyFn&, const std::remove_reference_t<ItemT>&>> requires(::sus::ops::Ord<Key> && !std::is_reference_v<Key>) Option<Item> min_by_key(KeyFn fn) && noexcept; template <IntoIteratorAny Other, int&..., class OtherItem = typename IntoIteratorOutputType<Other>::Item> requires(::sus::ops::Eq<ItemT, OtherItem>) bool ne(Other&& other) && noexcept; Option<Item> nth(usize n) noexcept; Option<Item> nth_back(usize n) noexcept requires(DoubleEndedIterator<Iter, Item>); template <IntoIteratorAny Other, int&..., class OtherItem = typename IntoIteratorOutputType<Other>::Item> requires(::sus::ops::PartialOrd<ItemT, OtherItem>) constexpr std::partial_ordering partial_cmp(Other&& other) && noexcept; template <IntoIteratorAny Other, int&..., class OtherItem = typename IntoIteratorOutputType<Other>::Item> constexpr std::partial_ordering partial_cmp_by( Other&& other, ::sus::fn::FnMut<std::partial_ordering( const std::remove_reference_t<Item>&, const std::remove_reference_t<OtherItem>&)> auto cmp) && noexcept; template <class B> requires(::sus::construct::Default<B> && Extend<B, ItemT>) sus::Tuple<B, B> partition( ::sus::fn::FnMutRef<bool(const std::remove_reference_t<Item>&)> pred) && noexcept; Iterator<Item> auto peekable() && noexcept; Option<usize> position(::sus::fn::FnMutRef<bool(Item&&)> pred) noexcept; template <class P = ItemT> requires(Product<P, ItemT>) constexpr P product() && noexcept; auto range() && noexcept; template <::sus::fn::FnMut<ItemT(ItemT, ItemT)> F, int&..., class R = std::invoke_result_t<F&, ItemT&&, ItemT&&>> requires(!std::is_reference_v<ItemT> || std::is_reference_v<R>) Option<Item> reduce(F f) && noexcept; Iterator<Item> auto rev() && noexcept requires(DoubleEndedIterator<Iter, Item>); constexpr Option<Item> rfind( ::sus::fn::FnMut<bool(const std::remove_reference_t<Item>&)> auto pred) noexcept requires(DoubleEndedIterator<Iter, Item>); template <class B, ::sus::fn::FnMut<::sus::fn::NonVoid(B, ItemT)> F> requires(DoubleEndedIterator<Iter, ItemT> && std::convertible_to<std::invoke_result_t<F&, B &&, ItemT &&>, B> && (!std::is_reference_v<B> || std::is_reference_v<std::invoke_result_t<F&, B &&, ItemT &&>>)) constexpr B rfold(B init, F f) && noexcept; Option<usize> rposition(::sus::fn::FnMutRef<bool(Item&&)> pred) noexcept requires(DoubleEndedIterator<Iter, Item> && ExactSizeIterator<Iter, Item>); template < class State, ::sus::fn::FnMut<::sus::fn::NonVoid(State&, ItemT&&)> F, int&..., class R = std::invoke_result_t<F&, State&, ItemT&&>, class InnerR = ::sus::option::__private::IsOptionType<R>::inner_type, class B = ::sus::fn::FnMutBox<R(State&, Item&&)>> requires(::sus::option::__private::IsOptionType<R>::value && ::sus::construct::Into<F, B>) Iterator<InnerR> auto scan(State initial_state, F f) && noexcept; Iterator<Item> auto skip(usize n) && noexcept; Iterator<Item> auto skip_while( ::sus::fn::FnMutBox<bool(const std::remove_reference_t<Item>&)> pred) && noexcept; Iterator<Item> auto step_by(usize step) && noexcept; template <class P = ItemT> requires(Sum<P, ItemT>) constexpr P sum() && noexcept; constexpr Iterator<Item> auto take(usize n) && noexcept; constexpr Iterator<Item> auto take_while( ::sus::fn::FnMut<bool(const std::remove_reference_t<Item>&)> auto pred) && noexcept; template <class B, ::sus::fn::FnMut<::sus::fn::NonVoid(B, ItemT)> F, int&..., class R = std::invoke_result_t<F&, B&&, ItemT&&>> requires(::sus::ops::Try<R> && std::convertible_to<typename ::sus::ops::TryImpl<R>::Output, B>) R try_fold(B init, F f) noexcept; template <class B, ::sus::fn::FnMut<::sus::fn::NonVoid(B, ItemT)> F, int&..., class R = std::invoke_result_t<F&, B&&, ItemT&&>> requires(DoubleEndedIterator<Iter, ItemT> && ::sus::ops::Try<R> && std::convertible_to<typename ::sus::ops::TryImpl<R>::Output, B>) R try_rfold(B init, F f) noexcept; template <::sus::fn::FnMut<::sus::fn::NonVoid(ItemT)> F, int&..., class R = std::invoke_result_t<F&, ItemT&&>> requires(::sus::ops::Try<R>) R try_for_each(typename ::sus::ops::TryImpl<R>::Output success, F f) noexcept; template <class ContainerA, class ContainerB, int&..., class ItemA = ::sus::option::__private::IsTupleOfSizeTwo<ItemT>::first_type, class ItemB = ::sus::option::__private::IsTupleOfSizeTwo<ItemT>::second_type> requires(::sus::option::__private::IsTupleOfSizeTwo<ItemT>::value && ::sus::construct::Default<ContainerA> && ::sus::construct::Default<ContainerB> && Extend<ContainerA, ItemA> && Extend<ContainerB, ItemB>) constexpr sus::Tuple<ContainerA, ContainerB> unzip() && noexcept; template <IntoIteratorAny Other, int&..., class OtherItem = typename IntoIteratorOutputType<Other>::Item> constexpr Iterator<sus::Tuple<ItemT, OtherItem>> auto zip( Other&& other) && noexcept; template <IntoIteratorAny Other, int&..., class OtherItem = typename IntoIteratorOutputType<Other>::Item> requires(::sus::ops::WeakOrd<ItemT, OtherItem>) std::weak_ordering weak_cmp(Other&& other) && noexcept; template <IntoIteratorAny Other, int&..., class OtherItem = typename IntoIteratorOutputType<Other>::Item> std::weak_ordering weak_cmp_by(Other&& other, ::sus::fn::FnMutBox<std::weak_ordering( const std::remove_reference_t<Item>&, const std::remove_reference_t<OtherItem>&)> cmp) && noexcept; template <FromIterator<ItemT> C> FromIterator<ItemT> auto collect() && noexcept; ::sus::containers::Vec<ItemT> collect_vec() && noexcept; }; template <class Iter, class Item> constexpr bool IteratorBase<Iter, Item>::all( ::sus::fn::FnMut<bool(Item)> auto f) noexcept { while (true) { Option<Item> item = as_subclass_mut().next(); if (item.is_none()) return true; if (!::sus::fn::call_mut( f, ::sus::move(item).unwrap_unchecked(::sus::marker::unsafe_fn))) return false; } } template <class Iter, class Item> constexpr bool IteratorBase<Iter, Item>::any( ::sus::fn::FnMut<bool(Item)> auto f) noexcept { while (true) { Option<Item> item = as_subclass_mut().next(); if (item.is_none()) return false; if (::sus::fn::call_mut( f, ::sus::move(item).unwrap_unchecked(::sus::marker::unsafe_fn))) return true; } } template <class Iter, class Item> constexpr Iterator<Item> auto IteratorBase<Iter, Item>::by_ref() & noexcept { return ByRef<Iter>::with(as_subclass_mut()); } template <class Iter, class Item> template <IntoIterator<Item> Other> constexpr Iterator<Item> auto IteratorBase<Iter, Item>::chain( Other&& other) && noexcept { using Chain = Chain<Iter, IntoIteratorOutputType<Other>>; return Chain::with(static_cast<Iter&&>(*this), ::sus::move(other).into_iter()); } template <class Iter, class Item> Iterator<std::remove_cvref_t<Item>> auto IteratorBase<Iter, Item>::cloned() && noexcept requires(::sus::mem::Clone<Item>) { using Cloned = Cloned<Iter>; return Cloned::with(static_cast<Iter&&>(*this)); } template <class Iter, class Item> template <IntoIteratorAny Other, int&..., class OtherItem> requires(::sus::ops::Ord<Item, OtherItem>) std::strong_ordering IteratorBase<Iter, Item>::cmp(Other&& other) && noexcept { return static_cast<Iter&&>(*this).cmp_by( ::sus::move(other), [](const std::remove_reference_t<Item>& x, const std::remove_reference_t<OtherItem>& y) -> std::strong_ordering { return x <=> y; }); } template <class Iter, class Item> template <IntoIteratorAny Other, int&..., class OtherItem> std::strong_ordering IteratorBase<Iter, Item>::cmp_by( Other&& other, ::sus::fn::FnMutBox<std::strong_ordering( const std::remove_reference_t<Item>&, const std::remove_reference_t<OtherItem>&)> cmp) && noexcept { return __private::iter_compare<std::strong_ordering, Item, OtherItem>( static_cast<Iter&&>(*this), ::sus::move(other).into_iter(), ::sus::move(cmp)); } template <class Iter, class Item> Iterator<std::remove_cvref_t<Item>> auto IteratorBase<Iter, Item>::copied() && noexcept requires(::sus::mem::Copy<Item>) { using Copied = Copied<Iter>; return Copied::with(static_cast<Iter&&>(*this)); } template <class Iter, class Item> constexpr ::sus::num::usize IteratorBase<Iter, Item>::count() && noexcept { auto c = 0_usize; while (as_subclass_mut().next().is_some()) c += 1_usize; return c; } template <class Iter, class Item> constexpr Iterator<Item> auto IteratorBase<Iter, Item>::cycle() && noexcept requires(::sus::mem::Clone<Iter>) { using Cycle = Cycle<Iter>; return Cycle::with(static_cast<Iter&&>(*this)); } template <class Iter, class Item> constexpr auto IteratorBase<Iter, Item>::enumerate() && noexcept { using Enumerate = Enumerate<Iter>; return Enumerate::with(static_cast<Iter&&>(*this)); } template <class Iter, class Item> template <IntoIteratorAny Other, int&..., class OtherItem> requires(::sus::ops::Eq<Item, OtherItem>) constexpr bool IteratorBase<Iter, Item>::eq(Other&& other) && noexcept { return static_cast<Iter&&>(*this).eq_by( ::sus::move(other), [](const std::remove_reference_t<Item>& x, const std::remove_reference_t<OtherItem>& y) { return x == y; }); } template <class Iter, class Item> template <IntoIteratorAny Other, int&..., class OtherItem> constexpr bool IteratorBase<Iter, Item>::eq_by( Other&& other, ::sus::fn::FnMut<bool(const std::remove_reference_t<Item>&, const std::remove_reference_t<OtherItem>&)> auto eq_fn) && noexcept { return __private::iter_compare_eq<Item, OtherItem>( static_cast<Iter&&>(*this), ::sus::move(other).into_iter(), ::sus::move(eq_fn)); } template <class Iter, class Item> constexpr Iterator<Item> auto IteratorBase<Iter, Item>::filter( ::sus::fn::FnMut<bool(const std::remove_reference_t<Item>&)> auto pred) && noexcept { using Filter = Filter<Iter, decltype(pred)>; return Filter::with(::sus::move(pred), static_cast<Iter&&>(*this)); } template <class Iter, class Item> template <::sus::fn::FnMut<::sus::fn::NonVoid(Item&&)> MapFn, int&..., class R, class InnerR> requires(::sus::option::__private::IsOptionType<R>::value) constexpr Iterator<InnerR> auto IteratorBase<Iter, Item>::filter_map( MapFn f) && noexcept { using FilterMap = FilterMap<InnerR, Iter, decltype(f)>; return FilterMap::with(::sus::move(f), static_cast<Iter&&>(*this)); } template <class Iter, class Item> constexpr Option<Item> IteratorBase<Iter, Item>::find( ::sus::fn::FnMut<bool(const std::remove_reference_t<Item>&)> auto pred) noexcept { while (true) { Option<Item> o = as_subclass_mut().next(); if (o.is_none() || ::sus::fn::call_mut(pred, o.as_value())) return o; } } template <class Iter, class Item> template <::sus::fn::FnMut<::sus::fn::NonVoid(Item&&)> FindFn, int&..., class R, class InnerR> requires(::sus::option::__private::IsOptionType<R>::value) constexpr Option<InnerR> IteratorBase<Iter, Item>::find_map(FindFn f) noexcept { while (true) { Option<Option<InnerR>> o = as_subclass_mut().next().map(f); if (o.is_none()) return sus::Option<InnerR>(); if (o.as_value().is_some()) return sus::move(o).flatten(); } } template <class Iter, class Item> template <::sus::fn::FnMut<::sus::fn::NonVoid(Item&&)> F, int&..., class R, class InnerR> requires(IntoIteratorAny<R>) constexpr Iterator<InnerR> auto IteratorBase<Iter, Item>::flat_map( F fn) && noexcept { using Flatten = FlatMap<R, Iter, F>; return Flatten::with(::sus::move_into(fn), static_cast<Iter&&>(*this)); } template <class Iter, class Item> constexpr auto IteratorBase<Iter, Item>::flatten() && noexcept requires(IntoIteratorAny<Item>) { using Flatten = Flatten<IntoIteratorOutputType<Item>, Iter>; return Flatten::with(static_cast<Iter&&>(*this)); } template <class Iter, class Item> template <class B, ::sus::fn::FnMut<::sus::fn::NonVoid(B, Item)> F> requires(std::convertible_to<std::invoke_result_t<F&, B &&, Item &&>, B> && (!std::is_reference_v<B> || std::is_reference_v<std::invoke_result_t<F&, B &&, Item &&>>)) constexpr B IteratorBase<Iter, Item>::fold(B init, F f) && noexcept { if constexpr (std::is_reference_v<B>) { std::remove_reference_t<B>* out = ::sus::mem::addressof(init); while (true) { if (Option<Item> o = as_subclass_mut().next(); o.is_none()) return *out; else out = ::sus::mem::addressof( ::sus::fn::call_mut(f, *out, sus::move(o).unwrap())); } } else { while (true) { if (Option<Item> o = as_subclass_mut().next(); o.is_none()) return init; else init = ::sus::fn::call_mut(f, ::sus::move(init), sus::move(o).unwrap()); } } } template <class Iter, class Item> template <::sus::fn::FnMut<void(Item&&)> F> constexpr void IteratorBase<Iter, Item>::for_each(F f) && noexcept { while (true) { if (Option<Item> o = as_subclass_mut().next(); o.is_none()) break; else ::sus::fn::call_mut(f, std::move(o).unwrap()); } } template <class Iter, class Item> constexpr Iterator<Item> auto IteratorBase<Iter, Item>::fuse() && noexcept { return Fuse<Iter>::with(static_cast<Iter&&>(*this)); } template <class Iter, class Item> template <::sus::fn::FnOnce<::sus::fn::NonVoid(Iter&&)> GenFn, int&..., class R, class GenR> requires(__private::IsGenerator<R>::value) Iterator<GenR> auto IteratorBase<Iter, Item>::generate( GenFn generator_fn) && noexcept { return ::sus::fn::call_once(::sus::move(generator_fn), static_cast<Iter&&>(*this)); } template <class Iter, class Item> template <IntoIteratorAny Other, int&..., class OtherItem> requires(::sus::ops::PartialOrd<Item, OtherItem>) constexpr bool IteratorBase<Iter, Item>::ge(Other&& other) && noexcept { return static_cast<Iter&&>(*this).partial_cmp(::sus::move(other)) >= 0; } template <class Iter, class Item> template <IntoIteratorAny Other, int&..., class OtherItem> requires(::sus::ops::PartialOrd<Item, OtherItem>) constexpr bool IteratorBase<Iter, Item>::gt(Other&& other) && noexcept { return static_cast<Iter&&>(*this).partial_cmp(::sus::move(other)) > 0; } template <class Iter, class Item> constexpr Iterator<Item> auto IteratorBase<Iter, Item>::inspect( ::sus::fn::FnMut<void(const std::remove_reference_t<Item>&)> auto fn) && noexcept { using Inspect = Inspect<Iter, decltype(fn)>; return Inspect::with(::sus::move_into(fn), static_cast<Iter&&>(*this)); } template <class Iter, class Item> constexpr bool IteratorBase<Iter, Item>::is_sorted() noexcept requires(::sus::ops::Ord<Item>) { return is_sorted_by( [](const std::remove_reference_t<Item>& a, const std::remove_reference_t<Item>& b) { return a <=> b; }); } template <class Iter, class Item> constexpr bool IteratorBase<Iter, Item>::is_sorted_by( ::sus::fn::FnMut<std::strong_ordering( const std::remove_reference_t<Item>&, const std::remove_reference_t<Item>&)> auto compare) noexcept { Option<Item> o = as_subclass_mut().next(); if (o.is_none()) return true; if constexpr (std::is_reference_v<Item>) { std::remove_reference_t<Item>* last = ::sus::mem::addressof(sus::move(o).unwrap()); return static_cast<Iter&&>(*this).all([&last, &compare](Item item) -> bool { auto ord = ::sus::fn::call_mut(compare, *last, item); if (ord > 0) return false; last = ::sus::mem::addressof(item); return true; }); } else { Item last = sus::move(o).unwrap(); return static_cast<Iter&&>(*this).all([&last, &compare](Item item) -> bool { auto ord = ::sus::fn::call_mut(compare, last, item); if (ord > 0) return false; last = sus::move(item); return true; }); } } template <class Iter, class Item> template <IntoIteratorAny Other, int&..., class OtherItem> requires(::sus::ops::PartialOrd<Item, OtherItem>) constexpr bool IteratorBase<Iter, Item>::le(Other&& other) && noexcept { return static_cast<Iter&&>(*this).partial_cmp(::sus::move(other)) <= 0; } template <class Iter, class Item> template <IntoIteratorAny Other, int&..., class OtherItem> requires(::sus::ops::PartialOrd<Item, OtherItem>) constexpr bool IteratorBase<Iter, Item>::lt(Other&& other) && noexcept { return static_cast<Iter&&>(*this).partial_cmp(::sus::move(other)) < 0; } template <class Iter, class Item> constexpr Option<Item> IteratorBase<Iter, Item>::last() && noexcept { return static_cast<Iter&&>(*this).fold( Option<Item>(), [](Option<Item>&&, Item&& cur) { return Option<Item>::with(cur); }); } template <class Iter, class Item> template <class T, int&..., class R, class B> requires(!std::is_void_v<R> && Into<T, B>) Iterator<R> auto IteratorBase<Iter, Item>::map(T fn) && noexcept { using Map = Map<R, Iter>; return Map::with(sus::move_into(fn), static_cast<Iter&&>(*this)); } template <class Iter, class Item> template <class F, int&..., class R, class InnerR, class B> requires(::sus::option::__private::IsOptionType<R>::value && Into<F, B>) Iterator<InnerR> auto IteratorBase<Iter, Item>::map_while(F fn) && noexcept { using MapWhile = MapWhile<InnerR, Iter>; return MapWhile::with(sus::move_into(fn), static_cast<Iter&&>(*this)); } template <class Iter, class Item> Option<Item> IteratorBase<Iter, Item>::max() && noexcept requires(::sus::ops::Ord<Item>) { return static_cast<Iter&&>(*this).max_by( [](const std::remove_reference_t<Item>& a, const std::remove_reference_t<Item>& b) { return a <=> b; }); } template <class Iter, class Item> Option<Item> IteratorBase<Iter, Item>::max_by( sus::fn::FnMutRef< std::strong_ordering(const std::remove_reference_t<Item>&, const std::remove_reference_t<Item>&)> compare) && noexcept { return static_cast<Iter&&>(*this).reduce( [&compare](Item acc, Item item) -> Item { auto acc_cref = static_cast<const std::remove_reference_t<Item>&>(acc); if (::sus::fn::call_mut(compare, item, acc_cref) >= 0) return ::sus::forward<Item>(item); return ::sus::forward<Item>(acc); }); } template <class Iter, class Item> template < ::sus::fn::FnMut<::sus::fn::NonVoid(const std::remove_reference_t<Item>&)> KeyFn, int&..., class Key> requires(::sus::ops::Ord<Key> && !std::is_reference_v<Key>) Option<Item> IteratorBase<Iter, Item>::max_by_key(KeyFn fn) && noexcept { auto fold = [&fn](sus::Tuple<Key, Item>&& acc, Item&& item) { Key key = ::sus::fn::call_mut(fn, item); if (key >= acc.template at<0>()) return sus::Tuple<Key, Item>::with(::sus::move(key), ::sus::forward<Item>(item)); return ::sus::move(acc); }; auto first = as_subclass_mut().next(); if (first.is_none()) return Option<Item>(); Key first_key = fn(first.as_value()); return Option<Item>::with( static_cast<Iter&&>(*this) .fold(sus::Tuple<Key, Item>::with(first_key, ::sus::move(first).unwrap_unchecked( ::sus::marker::unsafe_fn)), fold) .template into_inner<1>()); } template <class Iter, class Item> Option<Item> IteratorBase<Iter, Item>::min() && noexcept requires(::sus::ops::Ord<Item>) { return static_cast<Iter&&>(*this).min_by( [](const std::remove_reference_t<Item>& a, const std::remove_reference_t<Item>& b) { return a <=> b; }); } template <class Iter, class Item> Option<Item> IteratorBase<Iter, Item>::min_by( sus::fn::FnMutRef< std::strong_ordering(const std::remove_reference_t<Item>&, const std::remove_reference_t<Item>&)> compare) && noexcept { return static_cast<Iter&&>(*this).reduce( [&compare](Item acc, Item item) -> Item { auto acc_cref = static_cast<const std::remove_reference_t<Item>&>(acc); if (::sus::fn::call_mut(compare, item, acc_cref) < 0) return ::sus::forward<Item>(item); return ::sus::forward<Item>(acc); }); } template <class Iter, class Item> template < ::sus::fn::FnMut<::sus::fn::NonVoid(const std::remove_reference_t<Item>&)> KeyFn, int&..., class Key> requires(::sus::ops::Ord<Key> && !std::is_reference_v<Key>) Option<Item> IteratorBase<Iter, Item>::min_by_key(KeyFn fn) && noexcept { auto fold = [&fn](sus::Tuple<Key, Item>&& acc, Item&& item) { Key key = ::sus::fn::call_mut(fn, item); if (key < acc.template at<0>()) return sus::Tuple<Key, Item>::with(::sus::move(key), ::sus::forward<Item>(item)); return ::sus::move(acc); }; auto first = as_subclass_mut().next(); if (first.is_none()) return Option<Item>(); Key first_key = fn(first.as_value()); return Option<Item>::with( static_cast<Iter&&>(*this) .fold(sus::Tuple<Key, Item>::with(first_key, ::sus::move(first).unwrap_unchecked( ::sus::marker::unsafe_fn)), fold) .template into_inner<1>()); } template <class Iter, class Item> template <IntoIteratorAny Other, int&..., class OtherItem> requires(::sus::ops::Eq<Item, OtherItem>) bool IteratorBase<Iter, Item>::ne(Other&& other) && noexcept { return !static_cast<Iter&&>(*this).eq(::sus::move(other)); } template <class Iter, class Item> Option<Item> IteratorBase<Iter, Item>::nth(usize n) noexcept { while (true) { if (n == 0u) return as_subclass_mut().next(); if (as_subclass_mut().next().is_none()) return Option<Item>(); n -= 1u; } } template <class Iter, class Item> Option<Item> IteratorBase<Iter, Item>::nth_back(usize n) noexcept requires(DoubleEndedIterator<Iter, Item>) { while (true) { if (n == 0u) return as_subclass_mut().next_back(); if (as_subclass_mut().next_back().is_none()) return Option<Item>(); n -= 1u; } } template <class Iter, class Item> template <IntoIteratorAny Other, int&..., class OtherItem> requires(::sus::ops::PartialOrd<Item, OtherItem>) constexpr std::partial_ordering IteratorBase<Iter, Item>::partial_cmp( Other&& other) && noexcept { return static_cast<Iter&&>(*this).partial_cmp_by( ::sus::move(other), [](const std::remove_reference_t<Item>& x, const std::remove_reference_t<OtherItem>& y) -> std::partial_ordering { return x <=> y; }); } template <class Iter, class Item> template <IntoIteratorAny Other, int&..., class OtherItem> constexpr std::partial_ordering IteratorBase<Iter, Item>::partial_cmp_by( Other&& other, ::sus::fn::FnMut<std::partial_ordering( const std::remove_reference_t<Item>&, const std::remove_reference_t<OtherItem>&)> auto cmp) && noexcept { return __private::iter_compare<std::partial_ordering, Item, OtherItem>( static_cast<Iter&&>(*this), ::sus::move(other).into_iter(), ::sus::move(cmp)); } template <class Iter, class Item> template <class B> requires(::sus::construct::Default<B> && Extend<B, Item>) sus::Tuple<B, B> IteratorBase<Iter, Item>::partition( ::sus::fn::FnMutRef<bool(const std::remove_reference_t<Item>&)> pred) && noexcept { B left; B right; auto extend = [&pred, &left, &right](Item&& i) mutable { if (::sus::fn::call_mut( pred, static_cast<const std::remove_reference_t<Item>&>(i))) { left.extend(::sus::Option<Item>::with(::sus::forward<Item>(i))); } else { right.extend(::sus::Option<Item>::with(::sus::forward<Item>(i))); } }; static_cast<Iter&&>(*this).for_each(extend); return sus::Tuple<B, B>::with(sus::move(left), sus::move(right)); } template <class Iter, class Item> Iterator<Item> auto IteratorBase<Iter, Item>::peekable() && noexcept { using Peekable = Peekable<Iter>; return Peekable::with(static_cast<Iter&&>(*this)); } template <class Iter, class Item> Option<usize> IteratorBase<Iter, Item>::position( ::sus::fn::FnMutRef<bool(Item&&)> pred) noexcept { usize pos; while (true) { Option<Item> o = as_subclass_mut().next(); if (o.is_none()) return Option<usize>(); if (::sus::fn::call_mut( pred, ::sus::move(o).unwrap_unchecked(::sus::marker::unsafe_fn))) return Option<usize>::with(pos); pos += 1u; } } template <class Iter, class Item> template <class P> requires(Product<P, Item>) constexpr P IteratorBase<Iter, Item>::product() && noexcept { return P::from_product(static_cast<Iter&&>(*this)); } template <class Iter, class Item> auto IteratorBase<Iter, Item>::range() && noexcept { return IteratorRange<Iter>::with(static_cast<Iter&&>(*this)); } template <class Iter, class Item> template <::sus::fn::FnMut<Item(Item, Item)> F, int&..., class R> requires(!std::is_reference_v<Item> || std::is_reference_v<R>) Option<Item> IteratorBase<Iter, Item>::reduce(F f) && noexcept { Option<Item> first = as_subclass_mut().next(); if (first.is_some()) { first = Option<Item>::with(static_cast<Iter&&>(*this).template fold<Item>( ::sus::move(first).unwrap_unchecked(::sus::marker::unsafe_fn), ::sus::move(f))); } return first; } template <class Iter, class Item> Iterator<Item> auto IteratorBase<Iter, Item>::rev() && noexcept requires(DoubleEndedIterator<Iter, Item>) { using Reverse = Reverse<Iter>; return Reverse::with(static_cast<Iter&&>(*this)); } template <class Iter, class Item> constexpr Option<Item> IteratorBase<Iter, Item>::rfind( ::sus::fn::FnMut<bool(const std::remove_reference_t<Item>&)> auto pred) noexcept requires(DoubleEndedIterator<Iter, Item>) { while (true) { Option<Item> o = as_subclass_mut().next_back(); if (o.is_none() || ::sus::fn::call_mut(pred, o.as_value())) return o; } } template <class Iter, class Item> template <class B, ::sus::fn::FnMut<::sus::fn::NonVoid(B, Item)> F> requires(DoubleEndedIterator<Iter, Item> && std::convertible_to<std::invoke_result_t<F&, B &&, Item &&>, B> && (!std::is_reference_v<B> || std::is_reference_v<std::invoke_result_t<F&, B &&, Item &&>>)) constexpr B IteratorBase<Iter, Item>::rfold(B init, F f) && noexcept { while (true) { if (Option<Item> o = as_subclass_mut().next_back(); o.is_none()) return init; else init = ::sus::fn::call_mut(f, ::sus::move(init), sus::move(o).unwrap()); } } template <class Iter, class Item> Option<usize> IteratorBase<Iter, Item>::rposition( ::sus::fn::FnMutRef<bool(Item&&)> pred) noexcept requires(DoubleEndedIterator<Iter, Item> && ExactSizeIterator<Iter, Item>) { usize pos = as_subclass().exact_size_hint(); while (true) { Option<Item> o = as_subclass_mut().next_back(); if (o.is_none()) return Option<usize>(); pos -= 1u; if (::sus::fn::call_mut( pred, ::sus::move(o).unwrap_unchecked(::sus::marker::unsafe_fn))) return Option<usize>::with(pos); } } template <class Iter, class Item> template <class State, ::sus::fn::FnMut<::sus::fn::NonVoid(State&, Item&&)> F, int&..., class R, class InnerR, class B> requires(::sus::option::__private::IsOptionType<R>::value && ::sus::construct::Into<F, B>) Iterator<InnerR> auto IteratorBase<Iter, Item>::scan(State initial_state, F f) && noexcept { using Scan = Scan<InnerR, State, Iter>; return Scan::with(::sus::move(initial_state), ::sus::move_into(f), static_cast<Iter&&>(*this)); } template <class Iter, class Item> Iterator<Item> auto IteratorBase<Iter, Item>::skip(usize n) && noexcept { using Skip = Skip<Iter>; return Skip::with(n, static_cast<Iter&&>(*this)); } template <class Iter, class Item> Iterator<Item> auto IteratorBase<Iter, Item>::skip_while( ::sus::fn::FnMutBox<bool(const std::remove_reference_t<Item>&)> pred) && noexcept { using SkipWhile = SkipWhile<Iter>; return SkipWhile::with(::sus::move(pred), static_cast<Iter&&>(*this)); } template <class Iter, class Item> Iterator<Item> auto IteratorBase<Iter, Item>::step_by(usize step) && noexcept { using StepBy = StepBy<Iter>; return StepBy::with(step, static_cast<Iter&&>(*this)); } template <class Iter, class Item> template <class P> requires(Sum<P, Item>) constexpr P IteratorBase<Iter, Item>::sum() && noexcept { return P::from_sum(static_cast<Iter&&>(*this)); } template <class Iter, class Item> constexpr Iterator<Item> auto IteratorBase<Iter, Item>::take( usize n) && noexcept { using Take = Take<Iter>; return Take::with(n, static_cast<Iter&&>(*this)); } template <class Iter, class Item> constexpr Iterator<Item> auto IteratorBase<Iter, Item>::take_while( ::sus::fn::FnMut<bool(const std::remove_reference_t<Item>&)> auto pred) && noexcept { using TakeWhile = TakeWhile<Iter, decltype(pred)>; return TakeWhile::with(::sus::move(pred), static_cast<Iter&&>(*this)); } template <class Iter, class Item> template <class B, ::sus::fn::FnMut<::sus::fn::NonVoid(B, Item)> F, int&..., class R> requires(::sus::ops::Try<R> && std::convertible_to<typename ::sus::ops::TryImpl<R>::Output, B>) R IteratorBase<Iter, Item>::try_fold(B init, F f) noexcept { while (true) { if (Option<Item> o = as_subclass_mut().next(); o.is_none()) return ::sus::ops::try_from_output<R>(::sus::move(init)); else { R out = ::sus::fn::call_mut(f, ::sus::move(init), sus::move(o).unwrap()); if (!::sus::ops::try_is_success(out)) return out; init = ::sus::ops::try_into_output(::sus::move(out)); } } } template <class Iter, class Item> template <class B, ::sus::fn::FnMut<::sus::fn::NonVoid(B, Item)> F, int&..., class R> requires(DoubleEndedIterator<Iter, Item> && ::sus::ops::Try<R> && std::convertible_to<typename ::sus::ops::TryImpl<R>::Output, B>) R IteratorBase<Iter, Item>::try_rfold(B init, F f) noexcept { while (true) { if (Option<Item> o = as_subclass_mut().next_back(); o.is_none()) return ::sus::ops::try_from_output<R>(::sus::move(init)); else { R out = ::sus::fn::call_mut(f, ::sus::move(init), sus::move(o).unwrap()); if (!::sus::ops::try_is_success(out)) return out; init = ::sus::ops::try_into_output(::sus::move(out)); } } } template <class Iter, class Item> template <::sus::fn::FnMut<::sus::fn::NonVoid(Item)> F, int&..., class R> requires(::sus::ops::Try<R>) R IteratorBase<Iter, Item>::try_for_each( typename ::sus::ops::TryImpl<R>::Output success, F f) noexcept { R out = ::sus::ops::try_from_output<R>(::sus::move(success)); while (true) { if (Option<Item> o = as_subclass_mut().next(); o.is_none()) { break; } else { R test = ::sus::fn::call_mut(f, std::move(o).unwrap()); if (!::sus::ops::try_is_success(test)) { out = ::sus::move(test); break; } } } return out; } template <class Iter, class Item> template <class ContainerA, class ContainerB, int&..., class ItemA, class ItemB> requires(::sus::option::__private::IsTupleOfSizeTwo<Item>::value && ::sus::construct::Default<ContainerA> && ::sus::construct::Default<ContainerB> && Extend<ContainerA, ItemA> && Extend<ContainerB, ItemB>) sus::Tuple<ContainerA, ContainerB> constexpr IteratorBase<Iter, Item>::unzip() && noexcept { auto out = sus::Tuple<ContainerA, ContainerB>(); out.template extend<ItemA, ItemB>(static_cast<Iter&&>(*this)); return out; } template <class Iter, class Item> template <IntoIteratorAny Other, int&..., class OtherItem> constexpr Iterator<sus::Tuple<Item, OtherItem>> auto IteratorBase<Iter, Item>::zip(Other&& other) && noexcept { using Zip = Zip<Iter, IntoIteratorOutputType<Other>>; return Zip::with( sus::tuple(static_cast<Iter&&>(*this), sus::move(other).into_iter())); } template <class Iter, class Item> template <IntoIteratorAny Other, int&..., class OtherItem> requires(::sus::ops::WeakOrd<Item, OtherItem>) std::weak_ordering IteratorBase<Iter, Item>::weak_cmp( Other&& other) && noexcept { return static_cast<Iter&&>(*this).weak_cmp_by( ::sus::move(other), [](const std::remove_reference_t<Item>& x, const std::remove_reference_t<OtherItem>& y) -> std::weak_ordering { return x <=> y; }); } template <class Iter, class Item> template <IntoIteratorAny Other, int&..., class OtherItem> std::weak_ordering IteratorBase<Iter, Item>::weak_cmp_by( Other&& other, ::sus::fn::FnMutBox<std::weak_ordering( const std::remove_reference_t<Item>&, const std::remove_reference_t<OtherItem>&)> cmp) && noexcept { return __private::iter_compare<std::weak_ordering, Item, OtherItem>( static_cast<Iter&&>(*this), ::sus::move(other).into_iter(), ::sus::move(cmp)); } template <class Iter, class Item> template <FromIterator<Item> C> FromIterator<Item> auto IteratorBase<Iter, Item>::collect() && noexcept { return from_iter<C>(static_cast<Iter&&>(*this)); } template <class Iter, class Item> ::sus::containers::Vec<Item> IteratorBase<Iter, Item>::collect_vec() && noexcept { return from_iter<::sus::containers::Vec<Item>>(static_cast<Iter&&>(*this)); } } namespace sus::containers::__private { template <class... Ts> struct ArrayMarker { constexpr inline ArrayMarker(::sus::tuple_type::Tuple<Ts&&...>&& values) : values(::sus::move(values)){}; ::sus::tuple_type::Tuple<Ts&&...> values; template <class U> inline constexpr operator Array<U, sizeof...(Ts)>() && noexcept { auto make_array = [this]<size_t... Is>(std::integer_sequence<size_t, Is...>) { return Array<U, sizeof...(Is)>::with( ::sus::forward<Ts>(values.template at_mut<Is>())...); }; return make_array(std::make_integer_sequence<size_t, sizeof...(Ts)>()); } template <class T> inline constexpr Array<T, sizeof...(Ts)> construct() && noexcept { return ::sus::move(*this); } template <int&..., class T = ::sus::choice_type::__private::PackFirst<Ts...>> requires(... && std::same_as<T, Ts>) inline constexpr Array<T, sizeof...(Ts)> construct() && noexcept { return ::sus::move(*this); } }; } namespace sus::containers { template <::sus::mem::Move ItemT, size_t N> struct [[nodiscard]] ArrayIntoIter final : public ::sus::iter::IteratorBase<ArrayIntoIter<ItemT, N>, ItemT> { public: using Item = ItemT; static constexpr auto with(Array<Item, N>&& array) noexcept { return ArrayIntoIter(::sus::move(array)); } constexpr ArrayIntoIter clone() const noexcept requires(::sus::mem::Clone<Array<ItemT, N>>) { return ArrayIntoIter(::sus::clone(array_), front_index_, back_index_); } constexpr Option<Item> next() noexcept { if constexpr (N == 0) { return Option<Item>(); } else { if (front_index_ == back_index_) [[unlikely]] return Option<Item>(); Item& item = array_.get_unchecked_mut( ::sus::marker::unsafe_fn, ::sus::mem::replace(front_index_, front_index_ + 1_usize)); return Option<Item>::with(move(item)); } } constexpr ::sus::iter::SizeHint size_hint() const noexcept { ::sus::num::usize remaining = back_index_ - front_index_; return ::sus::iter::SizeHint( remaining, ::sus::Option<::sus::num::usize>::with(remaining)); } constexpr Option<Item> next_back() noexcept { if constexpr (N == 0) { return Option<Item>(); } else { if (front_index_ == back_index_) [[unlikely]] return Option<Item>(); back_index_ -= 1u; Item& item = array_.get_unchecked_mut(::sus::marker::unsafe_fn, back_index_); return Option<Item>::with(move(item)); } } constexpr ::sus::num::usize exact_size_hint() const noexcept { return back_index_ - front_index_; } private: constexpr ArrayIntoIter(Array<Item, N>&& array) noexcept : array_(::sus::move(array)) {} constexpr ArrayIntoIter(Array<Item, N>&& array, usize front, usize back) noexcept : array_(::sus::move(array)), front_index_(front), back_index_(back) {} Array<Item, N> array_; usize front_index_ = 0_usize; usize back_index_ = N; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(front_index_), decltype(back_index_), decltype(array_)>; }; } static_assert(1 == 0 || 1 == 1); namespace sus::iter { struct IterRefCounter; struct IterRef final { constexpr IterRef(usize* ptr) noexcept : count_ptr_(ptr) { inc(); } constexpr ~IterRef() noexcept { dec(); } constexpr IterRef(const IterRef& rhs) noexcept : count_ptr_(rhs.count_ptr_) { inc(); } constexpr IterRef& operator=(const IterRef& rhs) noexcept { dec(); count_ptr_ = rhs.count_ptr_; inc(); return *this; } constexpr IterRef(IterRef&& rhs) noexcept : count_ptr_(::sus::mem::replace(rhs.count_ptr_, nullptr)) {} constexpr IterRef& operator=(IterRef&& rhs) noexcept { dec(); count_ptr_ = ::sus::mem::replace(rhs.count_ptr_, nullptr); return *this; } constexpr IterRefCounter to_view() const noexcept; private: usize* count_ptr_; constexpr void inc() { if (count_ptr_) *count_ptr_ += 1u; } constexpr void dec() { if (count_ptr_) *count_ptr_ -= 1u; } static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(count_ptr_)>; static_assert(SusUnsafeTrivialRelocate, "Type is not trivially relocatable"); }; struct IterRefCounter final { static constexpr IterRefCounter for_owner() noexcept { return IterRefCounter(FOR_OWNER, 0_usize); } static constexpr IterRefCounter empty_for_view() noexcept { return IterRefCounter(FOR_VIEW, nullptr); } constexpr IterRef to_iter_from_owner() const noexcept { return IterRef(&count); } constexpr IterRef to_iter_from_view() const noexcept { return IterRef(count_ptr); } constexpr IterRefCounter to_view_from_owner() const noexcept { return IterRefCounter(FOR_VIEW, &count); } constexpr IterRefCounter to_view_from_view() const noexcept { return IterRefCounter(FOR_VIEW, count_ptr); } constexpr usize count_from_owner() const noexcept { return count; } constexpr IterRefCounter take_for_owner() & noexcept { return IterRefCounter(FOR_OWNER, ::sus::mem::replace(count, 0u)); } constexpr IterRefCounter take_for_view() & noexcept { return IterRefCounter(FOR_VIEW, ::sus::mem::replace(count_ptr, nullptr)); } private: friend struct IterRef; enum ForOwner { FOR_OWNER }; constexpr IterRefCounter(ForOwner, usize count) noexcept : count(count) {} enum ForView { FOR_VIEW }; constexpr IterRefCounter(ForView, usize* ptr) noexcept : count_ptr(ptr) {} union { mutable usize count; usize* count_ptr; }; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(count), decltype(count_ptr)>; static_assert(SusUnsafeTrivialRelocate, "Type is not trivially relocatable"); }; constexpr IterRefCounter IterRef::to_view() const noexcept { return IterRefCounter(IterRefCounter::FOR_VIEW, count_ptr_); } static_assert(sus::mem::Copy<IterRefCounter>); static_assert(sus::mem::Move<IterRefCounter>); static_assert(sus::mem::relocate_by_memcpy<IterRefCounter>); } namespace sus::ptr { template <class T> requires(!std::is_const_v<T>) void copy_nonoverlapping(::sus::marker::UnsafeFnMarker, const T* src, T* dst, ::sus::num::usize count) noexcept { ::sus::check(src != nullptr); ::sus::check(dst != nullptr); ::sus::check(reinterpret_cast<uintptr_t>(src) % alignof(T) == 0); ::sus::check(reinterpret_cast<uintptr_t>(dst) % alignof(T) == 0); ::sus::check((src < dst && src <= dst - count.primitive_value) || (dst < src && dst <= src - count.primitive_value)); if constexpr (::sus::mem::size_of<T>() > 1) { auto bytes = count.checked_mul(::sus::mem::size_of<T>()).expect("overflow"); memcpy(dst, src, size_t{bytes}); } else { memcpy(dst, src, size_t{count}); } } template <class T> requires(!std::is_const_v<T>) void copy(::sus::marker::UnsafeFnMarker, const T* src, T* dst, ::sus::num::usize count) noexcept { ::sus::check(src != nullptr); ::sus::check(dst != nullptr); ::sus::check(reinterpret_cast<uintptr_t>(src) % alignof(T) == 0); ::sus::check(reinterpret_cast<uintptr_t>(dst) % alignof(T) == 0); if constexpr (::sus::mem::size_of<T>() > 1) { auto bytes = count.checked_mul(::sus::mem::size_of<T>()).expect("overflow"); memmove(dst, src, size_t{bytes}); } else { memmove(dst, src, size_t{count}); } } } namespace sus::iter { using ::sus::option::Option; template <class ItemT> class Once; template <class Item> constexpr inline Once<Item> once(Option<Item> o) noexcept { return Once<Item>(::sus::move(o)); } template <class ItemT> class [[nodiscard]] Once final : public IteratorBase<Once<ItemT>, ItemT> { public: using Item = ItemT; constexpr Option<Item> next() noexcept { return single_.take(); } constexpr SizeHint size_hint() const noexcept { ::sus::num::usize rem = single_.is_some() ? 1u : 0u; return SizeHint(rem, ::sus::Option<::sus::num::usize>::with(rem)); } constexpr Option<Item> next_back() noexcept { return single_.take(); } constexpr usize exact_size_hint() const noexcept { return single_.is_some() ? 1u : 0u; } private: friend constexpr Once<Item> sus::iter::once<Item>(Option<Item> o) noexcept; constexpr Once(Option<Item> single) : single_(::sus::move(single)) {} Option<Item> single_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(single_)>; }; } namespace sus::ops::__private { template <class T, class U = T> concept VoidOrEq = (std::is_void_v<T> && std::is_void_v<U>) || ::sus::ops::Eq<T, U>; template <class T, class U = T> concept VoidOrOrd = (std::is_void_v<T> && std::is_void_v<U>) || ::sus::ops::Ord<T, U>; template <class T, class U = T> concept VoidOrWeakOrd = (std::is_void_v<T> && std::is_void_v<U>) || ::sus::ops::WeakOrd<T, U>; template <class T, class U = T> concept VoidOrPartialOrd = (std::is_void_v<T> && std::is_void_v<U>) || ::sus::ops::PartialOrd<T, U>; } namespace sus::result::__private { struct OkVoidMarker { template <class E> inline constexpr operator ::sus::result::Result<void, E>() const& noexcept { return Result<void, E>::with(); } template <class E> inline constexpr operator ::sus::result::Result<void, E>() && noexcept { return Result<void, E>::with(); } template <class E> inline constexpr ::sus::result::Result<void, E> construct() && noexcept { return ::sus::move(*this); } }; template <class T> struct OkMarker { constexpr inline OkMarker(T&& value) : value(::sus::forward<T>(value)){}; T&& value; template <class U, class E> requires(std::constructible_from<U, const T&>) inline constexpr operator ::sus::result::Result<U, E>() const& noexcept { static_assert( ::sus::construct::SafelyConstructibleFromReference<U, const T&>, "Unable to safely convert to a different reference type, as conversion " "would produce a reference to a temporary. The OkMarker's value type " "must match the Result's. For example a `Result<const i32&, E>` can " "not be constructed from an OkMarker holding `const i16&`, but it can " "be constructed from `i32&&`."); return Result<U, E>::with(static_cast<const T&>(value)); } template <class U, class E> inline constexpr operator ::sus::result::Result<U, E>() && noexcept { static_assert( ::sus::construct::SafelyConstructibleFromReference<U, T&&>, "Unable to safely convert to a different reference type, as conversion " "would produce a reference to a temporary. The OkMarker's value type " "must match the Result's. For example a `Result<const i32&, E>` can " "not be constructed from an OkMarker holding `const i16&`, but it can " "be constructed from `i32&&`."); return Result<U, E>::with(::sus::forward<T>(value)); } template <class E> inline constexpr ::sus::result::Result<::sus::mem::remove_rvalue_reference<T>, E> construct() && noexcept { return ::sus::move(*this); } template <class U, class E> inline constexpr ::sus::result::Result<U, E> construct() && noexcept { return ::sus::move(*this); } }; template <class E> struct ErrMarker { constexpr inline ErrMarker(E&& value) : value(::sus::forward<E>(value)){}; E&& value; template <class T, class F> requires(std::constructible_from<F, std::remove_reference_t<E>&>) inline constexpr operator ::sus::result::Result<T, F>() const& noexcept { return Result<T, F>::with_err(value); } template <class T, class F> inline constexpr operator ::sus::result::Result<T, F>() && noexcept { return Result<T, F>::with_err(::sus::forward<E>(value)); } template <class T, class F = std::remove_reference_t<E>> inline constexpr ::sus::result::Result<T, F> construct() && noexcept { return ::sus::move(*this); } }; } namespace sus::result::__private { enum class ResultState { IsErr = 0, IsOk = 1, IsMoved = 2 }; } namespace sus::result::__private { enum WithT { kWithT }; enum WithE { kWithE }; template <class T, class E> union Storage { constexpr Storage() {} template <std::convertible_to<T> U> constexpr Storage(WithT, const U& t) noexcept requires(sus::mem::Copy<T>) : ok_(t) {} template <std::convertible_to<T> U> constexpr Storage(WithT, U&& t) noexcept : ok_(::sus::move(t)) {} constexpr Storage(WithE, const E& e) noexcept requires(sus::mem::Copy<E>) : err_(e) {} constexpr Storage(WithE, E&& e) noexcept : err_(::sus::move(e)) {} constexpr ~Storage() requires(std::is_trivially_destructible_v<T> && std::is_trivially_destructible_v<E>) = default; constexpr ~Storage() requires(!(std::is_trivially_destructible_v<T> && std::is_trivially_destructible_v<E>)) { } constexpr Storage(const Storage&) noexcept requires(std::is_trivially_copy_constructible_v<T> && std::is_trivially_copy_constructible_v<E>) = default; constexpr Storage& operator=(const Storage&) requires(std::is_trivially_copy_assignable_v<T> && std::is_trivially_copy_assignable_v<E>) = default; constexpr Storage(Storage&&) requires(std::is_trivially_move_constructible_v<T> && std::is_trivially_move_constructible_v<E>) = default; constexpr Storage& operator=(Storage&&) requires(std::is_trivially_move_assignable_v<T> && std::is_trivially_move_assignable_v<E>) = default; constexpr inline void destroy_ok() noexcept { ok_.~T(); } constexpr inline void destroy_err() noexcept { err_.~E(); } [[no_unique_address]] T ok_; [[no_unique_address]] E err_; }; } namespace sus::result { using ::sus::iter::Once; using ::sus::mem::__private::IsTrivialCopyAssignOrRef; using ::sus::mem::__private::IsTrivialCopyCtorOrRef; using ::sus::mem::__private::IsTrivialDtorOrRef; using ::sus::mem::__private::IsTrivialMoveAssignOrRef; using ::sus::mem::__private::IsTrivialMoveCtorOrRef; using ::sus::ops::__private::VoidOrEq; using ::sus::ops::__private::VoidOrOrd; using ::sus::ops::__private::VoidOrPartialOrd; using ::sus::ops::__private::VoidOrWeakOrd; using ::sus::option::__private::StoragePointer; using ::sus::result::__private::ResultState; using ::sus::result::__private::Storage; enum class State : bool { Err = 0, Ok = 1, }; using State::Err; using State::Ok; template <class T, class E> class [[nodiscard]] Result final { static_assert(!std::is_reference_v<E>, "A reference Error type is not supported."); static_assert( !std::is_rvalue_reference_v<T>, "`Option<T&&> is not supported, use Option<T&> or Option<const T&."); static_assert(!std::is_void_v<E>, "A void Error type is not supported. Use Option<T> instead."); struct VoidType; using TUnlessVoid = std::conditional_t<std::is_void_v<T>, VoidType, T>; public: using OkType = T; using ErrType = E; static constexpr inline Result with() noexcept requires(std::is_void_v<T>) { return Result(WithOk); } static constexpr inline Result with(const TUnlessVoid& t) noexcept requires(!std::is_void_v<T> && !std::is_reference_v<T> && ::sus::mem::Copy<T>) { return Result(WithOk, t); } static constexpr inline Result with(TUnlessVoid&& t) noexcept requires(!std::is_void_v<T> && !std::is_reference_v<T>) { if constexpr (::sus::mem::Move<T>) { return Result(WithOk, move_ok_to_storage(t)); } else { static_assert(::sus::mem::Copy<T>, "All types should be Copy or Move."); return Result(WithOk, t); } } template <std::convertible_to<TUnlessVoid> U> __attribute__((pure)) static inline constexpr Result with(U&& t) noexcept requires(!std::is_void_v<T> && std::is_reference_v<T> && sus::construct::SafelyConstructibleFromReference<T, U &&>) { return Result(WithOk, move_ok_to_storage(t)); } static constexpr inline Result with_err(const E& e) noexcept requires(::sus::mem::Copy<E>) { return Result(WithErr, e); } static constexpr inline Result with_err(E&& e) noexcept requires(::sus::mem::Move<E>) { return Result(WithErr, ::sus::move(e)); } constexpr ~Result() requires((std::is_void_v<T> || IsTrivialDtorOrRef<T>) && IsTrivialDtorOrRef<E>) = default; constexpr inline ~Result() noexcept requires( !((std::is_void_v<T> || IsTrivialDtorOrRef<T>) && IsTrivialDtorOrRef<E>) ) { switch (state_) { case ResultState::IsMoved: break; case ResultState::IsOk: storage_.destroy_ok(); break; case ResultState::IsErr: storage_.destroy_err(); break; } } constexpr Result(const Result&) requires((std::is_void_v<T> || ::sus::mem::CopyOrRef<T>) && ::sus::mem::Copy<E> && (std::is_void_v<T> || IsTrivialCopyCtorOrRef<T>) && IsTrivialCopyCtorOrRef<E>) = default; constexpr Result(const Result& rhs) noexcept requires( (std::is_void_v<T> || ::sus::mem::CopyOrRef<T>) && ::sus::mem::Copy<E> && !((std::is_void_v<T> || IsTrivialCopyCtorOrRef<T>) && IsTrivialCopyCtorOrRef<E>) ) : state_(rhs.state_) { ::sus::check(state_ != ResultState::IsMoved); switch (state_) { case ResultState::IsOk: if constexpr (!std::is_void_v<T>) std::construct_at(&storage_.ok_, rhs.storage_.ok_); break; case ResultState::IsErr: std::construct_at(&storage_.err_, rhs.storage_.err_); break; case ResultState::IsMoved: ::sus::unreachable_unchecked(::sus::marker::unsafe_fn); } } constexpr Result(const Result&) requires(!((std::is_void_v<T> || ::sus::mem::CopyOrRef<T>) && ::sus::mem::Copy<E>)) = delete; constexpr Result& operator=(const Result& o) requires((std::is_void_v<T> || ::sus::mem::CopyOrRef<T>) && ::sus::mem::Copy<E> && (std::is_void_v<T> || IsTrivialCopyAssignOrRef<T>) && IsTrivialCopyAssignOrRef<E>) = default; constexpr Result& operator=(const Result& o) noexcept requires( (std::is_void_v<T> || ::sus::mem::CopyOrRef<T>) && ::sus::mem::Copy<E> && !((std::is_void_v<T> || IsTrivialCopyAssignOrRef<T>) && IsTrivialCopyAssignOrRef<E>) ) { check(o.state_ != ResultState::IsMoved); switch (state_) { case ResultState::IsOk: switch (state_ = o.state_) { case ResultState::IsOk: if constexpr (!std::is_void_v<T>) { storage_.ok_ = o.storage_.ok_; } break; case ResultState::IsErr: storage_.destroy_ok(); std::construct_at(&storage_.err_, o.storage_.err_); break; case ResultState::IsMoved: ::sus::unreachable_unchecked(::sus::marker::unsafe_fn); } break; case ResultState::IsErr: switch (state_ = o.state_) { case ResultState::IsErr: storage_.err_ = o.storage_.err_; break; case ResultState::IsOk: storage_.destroy_err(); if constexpr (!std::is_void_v<T>) std::construct_at(&storage_.ok_, o.storage_.ok_); break; case ResultState::IsMoved: ::sus::unreachable_unchecked(::sus::marker::unsafe_fn); } break; case ResultState::IsMoved: switch (state_ = o.state_) { case ResultState::IsErr: std::construct_at(&storage_.err_, o.storage_.err_); break; case ResultState::IsOk: if constexpr (!std::is_void_v<T>) std::construct_at(&storage_.ok_, o.storage_.ok_); break; case ResultState::IsMoved: ::sus::unreachable_unchecked(::sus::marker::unsafe_fn); } break; } return *this; } constexpr Result& operator=(const Result&) requires(!((std::is_void_v<T> || ::sus::mem::CopyOrRef<T>) && ::sus::mem::Copy<E>)) = delete; constexpr Result(Result&&) requires((std::is_void_v<T> || ::sus::mem::MoveOrRef<T>) && ::sus::mem::Move<E> && (std::is_void_v<T> || IsTrivialMoveCtorOrRef<T>) && IsTrivialMoveCtorOrRef<E>) = default; constexpr Result(Result&& rhs) noexcept requires( (std::is_void_v<T> || ::sus::mem::MoveOrRef<T>) && ::sus::mem::Move<E> && !((std::is_void_v<T> || IsTrivialMoveCtorOrRef<T>) && IsTrivialMoveCtorOrRef<E>) ) : state_(::sus::mem::replace(rhs.state_, ResultState::IsMoved)) { ::sus::check(state_ != ResultState::IsMoved); switch (state_) { case ResultState::IsOk: std::construct_at(&storage_.ok_, ::sus::move(rhs.storage_.ok_)); break; case ResultState::IsErr: std::construct_at(&storage_.err_, ::sus::move(rhs.storage_.err_)); break; case ResultState::IsMoved: ::sus::unreachable_unchecked(::sus::marker::unsafe_fn); } } constexpr Result(Result&&) requires(!((std::is_void_v<T> || ::sus::mem::MoveOrRef<T>) && ::sus::mem::Move<E>)) = delete; constexpr Result& operator=(Result&& o) requires((std::is_void_v<T> || ::sus::mem::MoveOrRef<T>) && ::sus::mem::Move<E> && (std::is_void_v<T> || IsTrivialMoveAssignOrRef<T>) && IsTrivialMoveAssignOrRef<E>) = default; constexpr Result& operator=(Result&& o) noexcept requires( (std::is_void_v<T> || ::sus::mem::MoveOrRef<T>) && ::sus::mem::Move<E> && !((std::is_void_v<T> || IsTrivialMoveAssignOrRef<T>) && IsTrivialMoveAssignOrRef<E>) ) { check(o.state_ != ResultState::IsMoved); switch (state_) { case ResultState::IsOk: switch (state_ = ::sus::mem::replace(o.state_, ResultState::IsMoved)) { case ResultState::IsOk: storage_.ok_ = ::sus::move(o.storage_.ok_); break; case ResultState::IsErr: storage_.destroy_ok(); std::construct_at(&storage_.err_, ::sus::move(o.storage_.err_)); break; case ResultState::IsMoved: ::sus::unreachable_unchecked(::sus::marker::unsafe_fn); } break; case ResultState::IsErr: switch (state_ = ::sus::mem::replace(o.state_, ResultState::IsMoved)) { case ResultState::IsErr: storage_.err_ = ::sus::move(o.storage_.err_); break; case ResultState::IsOk: storage_.destroy_err(); std::construct_at(&storage_.ok_, ::sus::move(o.storage_.ok_)); break; case ResultState::IsMoved: ::sus::unreachable_unchecked(::sus::marker::unsafe_fn); } break; case ResultState::IsMoved: switch (state_ = ::sus::mem::replace(o.state_, ResultState::IsMoved)) { case ResultState::IsErr: std::construct_at(&storage_.err_, ::sus::move(o.storage_.err_)); break; case ResultState::IsOk: std::construct_at(&storage_.ok_, ::sus::move(o.storage_.ok_)); break; case ResultState::IsMoved: ::sus::unreachable_unchecked(::sus::marker::unsafe_fn); } break; } return *this; } constexpr Result& operator=(Result&& o) requires(!(std::is_void_v<T> || ::sus::mem::MoveOrRef<T>) || !::sus::mem::Move<E>) = delete; constexpr Result clone() const& noexcept requires((std::is_void_v<T> || ::sus::mem::Clone<T>) && ::sus::mem::Clone<E> && !((std::is_void_v<T> || ::sus::mem::CopyOrRef<T>) && ::sus::mem::Copy<E>)) { ::sus::check(state_ != ResultState::IsMoved); switch (state_) { case ResultState::IsOk: if constexpr (std::is_void_v<T>) return Result(WithOk); else return Result(WithOk, ::sus::clone(storage_.ok_)); case ResultState::IsErr: return Result(WithErr, ::sus::clone(storage_.err_)); case ResultState::IsMoved: break; } ::sus::unreachable_unchecked(::sus::marker::unsafe_fn); } constexpr void clone_from(const Result& source) & requires((std::is_void_v<T> || ::sus::mem::Clone<T>) && ::sus::mem::Clone<E> && !((std::is_void_v<T> || ::sus::mem::CopyOrRef<T>) && ::sus::mem::Copy<E>)) { ::sus::check(source.state_ != ResultState::IsMoved); if (&source == this) [[unlikely]] return; if (state_ == source.state_) { switch (state_) { case ResultState::IsOk: if constexpr (!std::is_void_v<T>) ::sus::clone_into(storage_.ok_, source.storage_.ok_); break; case ResultState::IsErr: ::sus::clone_into(storage_.err_, source.storage_.err_); break; case ResultState::IsMoved: ::sus::unreachable_unchecked(::sus::marker::unsafe_fn); } } else { *this = source.clone(); } } template <::sus::iter::Iterator<Result<T, E>> Iter> requires ::sus::iter::Product<T> static constexpr Result from_product(Iter&& it) noexcept { class IterUntilNone final : public ::sus::iter::IteratorBase<IterUntilNone, T> { public: IterUntilNone(Iter& iter, Option<E>& err) : iter_(iter), err_(err) {} Option<T> next() noexcept { Option<Result<T, E>> next = iter_.next(); Option<T> out; if (next.is_some()) { Result<T, E> r = ::sus::move(next).unwrap_unchecked(::sus::marker::unsafe_fn); if (r.is_err()) { err_ = ::sus::move(r).err(); } else { out = ::sus::move(r).ok(); } } return out; } ::sus::iter::SizeHint size_hint() const noexcept { return ::sus::iter::SizeHint(0u, iter_.size_hint().upper); } private: Iter& iter_; Option<E>& err_; }; static_assert(::sus::iter::Iterator<IterUntilNone, T>); Option<E> err; auto out = Result::with(IterUntilNone(it, err).product()); if (err.is_some()) { out = Result::with_err( ::sus::move(err).unwrap_unchecked(::sus::marker::unsafe_fn)); } return out; } template <::sus::iter::Iterator<Result<T, E>> Iter> requires ::sus::iter::Sum<T> static constexpr Result from_sum(Iter&& it) noexcept { class IterUntilNone final : public ::sus::iter::IteratorBase<IterUntilNone, T> { public: IterUntilNone(Iter& iter, Option<E>& err) : iter_(iter), err_(err) {} Option<T> next() noexcept { Option<Result<T, E>> next = iter_.next(); Option<T> out; if (next.is_some()) { Result<T, E> r = ::sus::move(next).unwrap_unchecked(::sus::marker::unsafe_fn); if (r.is_err()) { err_ = ::sus::move(r).err(); } else { out = ::sus::move(r).ok(); } } return out; } ::sus::iter::SizeHint size_hint() const noexcept { return ::sus::iter::SizeHint(0u, iter_.size_hint().upper); } private: Iter& iter_; Option<E>& err_; }; static_assert(::sus::iter::Iterator<IterUntilNone, T>); Option<E> err; auto out = Result::with(IterUntilNone(it, err).sum()); if (err.is_some()) { out = Result::with_err( ::sus::move(err).unwrap_unchecked(::sus::marker::unsafe_fn)); } return out; } constexpr inline bool is_ok() const& noexcept { ::sus::check(state_ != ResultState::IsMoved); return state_ == ResultState::IsOk; } constexpr inline bool is_err() const& noexcept { ::sus::check(state_ != ResultState::IsMoved); return state_ == ResultState::IsErr; } constexpr inline operator State() const& noexcept { ::sus::check(state_ != ResultState::IsMoved); return static_cast<State>(state_); } constexpr inline Option<T> ok() && noexcept requires(!std::is_void_v<T>) { ::sus::check(state_ != ResultState::IsMoved); switch (::sus::mem::replace(state_, ResultState::IsMoved)) { case ResultState::IsOk: return Option<T>::with(static_cast<T>(::sus::mem::take_and_destruct( ::sus::marker::unsafe_fn, storage_.ok_))); case ResultState::IsErr: storage_.destroy_err(); return Option<T>(); case ResultState::IsMoved: break; } ::sus::unreachable_unchecked(::sus::marker::unsafe_fn); } constexpr inline Option<E> err() && noexcept { ::sus::check(state_ != ResultState::IsMoved); switch (::sus::mem::replace(state_, ResultState::IsMoved)) { case ResultState::IsOk: storage_.destroy_ok(); return Option<E>(); case ResultState::IsErr: return Option<E>::with(::sus::mem::take_and_destruct( ::sus::marker::unsafe_fn, storage_.err_)); case ResultState::IsMoved: break; } ::sus::unreachable_unchecked(::sus::marker::unsafe_fn); } constexpr const std::remove_reference_t<TUnlessVoid>& as_ok() const& requires(!std::is_void_v<T>) { ::sus::check(state_ == ResultState::IsOk); return storage_.ok_; } constexpr const std::remove_reference_t<E>& as_err() const& { ::sus::check(state_ == ResultState::IsErr); return storage_.err_; } constexpr inline T unwrap() && noexcept { ResultState was = ::sus::mem::replace(state_, ResultState::IsMoved); check_with_message( was == ResultState::IsOk, *"called `Result::unwrap()` on an `Err` value or moved Result"); if constexpr (!std::is_void_v<T>) { return ::sus::mem::take_and_destruct(::sus::marker::unsafe_fn, storage_.ok_); } } constexpr T unwrap_or_default() && noexcept requires(!std::is_reference_v<T> && (std::is_void_v<T> || ::sus::construct::Default<T>)) { ResultState was = ::sus::mem::replace(state_, ResultState::IsMoved); check_with_message( was != ResultState::IsMoved, *"called `Result::unwrap_or_default()` on a moved Result"); if constexpr (!std::is_void_v<T>) { if (was == ResultState::IsOk) { return ::sus::mem::take_and_destruct(::sus::marker::unsafe_fn, storage_.ok_); } else { return T(); } } } constexpr inline T unwrap_unchecked( ::sus::marker::UnsafeFnMarker) && noexcept { state_ = ResultState::IsMoved; if constexpr (!std::is_void_v<T>) { return ::sus::mem::take_and_destruct(::sus::marker::unsafe_fn, storage_.ok_); } } constexpr inline E unwrap_err() && noexcept { ResultState was = ::sus::mem::replace(state_, ResultState::IsMoved); check_with_message( was == ResultState::IsErr, *"called `Result::unwrap_err()` on an `Ok` value or moved Result"); return ::sus::mem::take_and_destruct(::sus::marker::unsafe_fn, storage_.err_); } constexpr inline E unwrap_err_unchecked( ::sus::marker::UnsafeFnMarker) && noexcept { state_ = ResultState::IsMoved; return ::sus::mem::take_and_destruct(::sus::marker::unsafe_fn, storage_.err_); } template <::sus::fn::FnOnce<T(E&&)> F> constexpr T unwrap_or_else(F&& op) && noexcept { if (is_ok()) { return ::sus::move(*this).unwrap_unchecked(::sus::marker::unsafe_fn); } else { return ::sus::fn::call_once( ::sus::move(op), ::sus::move(*this).unwrap_err_unchecked(::sus::marker::unsafe_fn)); } } constexpr Once<const std::remove_reference_t<TUnlessVoid>&> iter() const& noexcept requires(!std::is_void_v<T>) { ::sus::check(state_ != ResultState::IsMoved); if (state_ == ResultState::IsOk) { return ::sus::iter::once<const std::remove_reference_t<T>&>( Option<const std::remove_reference_t<T>&>::with( static_cast<const std::remove_reference_t<T>&>(storage_.ok_))); } else { return ::sus::iter::once<const std::remove_reference_t<T>&>( Option<const std::remove_reference_t<T>&>()); } } constexpr Once<const std::remove_reference_t<TUnlessVoid>&> iter() && noexcept requires(!std::is_void_v<T> && std::is_reference_v<T>) { ::sus::check(state_ != ResultState::IsMoved); if (::sus::mem::replace(state_, ResultState::IsMoved) == ResultState::IsOk) { return ::sus::iter::once<const std::remove_reference_t<T>&>( Option<const std::remove_reference_t<T>&>::with( static_cast<const std::remove_reference_t<T>&>(storage_.ok_))); } else { storage_.destroy_err(); return ::sus::iter::once<const std::remove_reference_t<T>&>( Option<const std::remove_reference_t<T>&>()); } } constexpr Once<TUnlessVoid&> iter_mut() & noexcept requires(!std::is_void_v<T>) { ::sus::check(state_ != ResultState::IsMoved); if (state_ == ResultState::IsOk) { return ::sus::iter::once<T&>(Option<T&>::with(storage_.ok_)); } else { return ::sus::iter::once<T&>(Option<T&>()); } } constexpr Once<TUnlessVoid&> iter_mut() && noexcept requires(!std::is_void_v<T> && std::is_reference_v<T>) { ::sus::check(state_ != ResultState::IsMoved); if (::sus::mem::replace(state_, ResultState::IsMoved) == ResultState::IsOk) { return ::sus::iter::once<T&>(Option<T&>::with(storage_.ok_)); } else { storage_.destroy_err(); return ::sus::iter::once<T&>(Option<T&>()); } } constexpr Once<T> into_iter() && noexcept requires(!std::is_void_v<T>) { ::sus::check(state_ != ResultState::IsMoved); if (::sus::mem::replace(state_, ResultState::IsMoved) == ResultState::IsOk) { return ::sus::iter::once<T>(Option<T>::with(::sus::mem::take_and_destruct( ::sus::marker::unsafe_fn, storage_.ok_))); } else { storage_.destroy_err(); return ::sus::iter::once<T>(Option<T>()); } } friend constexpr bool operator==(const Result& l, const Result& r) noexcept requires(VoidOrEq<T> && ::sus::ops::Eq<E>) { ::sus::check(l.state_ != ResultState::IsMoved); switch (l.state_) { case ResultState::IsOk: if constexpr (!std::is_void_v<T>) return r.is_ok() && l.storage_.ok_ == r.storage_.ok_; else return r.is_ok(); case ResultState::IsErr: return r.is_err() && l.storage_.err_ == r.storage_.err_; case ResultState::IsMoved: break; } ::sus::unreachable_unchecked(::sus::marker::unsafe_fn); } template <class U, class F> requires(VoidOrEq<T, U> && ::sus::ops::Eq<E, F>) friend constexpr bool operator==(const Result& l, const Result<U, F>& r) noexcept { ::sus::check(l.state_ != ResultState::IsMoved); switch (l.state_) { case ResultState::IsOk: if constexpr (!std::is_void_v<T>) return r.is_ok() && l.storage_.ok_ == r.storage_.ok_; else return r.is_ok(); case ResultState::IsErr: return r.is_err() && l.storage_.err_ == r.storage_.err_; case ResultState::IsMoved: break; } ::sus::unreachable_unchecked(::sus::marker::unsafe_fn); } template <class U, class F> requires(!(VoidOrEq<T, U> && ::sus::ops::Eq<E, F>)) friend constexpr bool operator==(const Result& l, const Result<U, F>& r) = delete; friend constexpr auto operator<=>(const Result& l, const Result& r) noexcept requires(VoidOrOrd<T> && ::sus::ops::Ord<E>) { ::sus::check(l.state_ != ResultState::IsMoved); switch (l.state_) { case ResultState::IsOk: if (r.is_ok()) { if constexpr (!std::is_void_v<T>) return std::strong_order(l.storage_.ok_, r.storage_.ok_); else return std::strong_ordering::equivalent; } else { return std::strong_ordering::greater; } case ResultState::IsErr: if (r.is_err()) return std::strong_order(l.storage_.err_, r.storage_.err_); else return std::strong_ordering::less; case ResultState::IsMoved: break; } ::sus::unreachable_unchecked(::sus::marker::unsafe_fn); } template <class U, class F> requires(VoidOrOrd<T, U> && ::sus::ops::Ord<E, F>) friend constexpr auto operator<=>(const Result& l, const Result<U, F>& r) noexcept { ::sus::check(l.state_ != ResultState::IsMoved); switch (l.state_) { case ResultState::IsOk: if (r.is_ok()) { if constexpr (!std::is_void_v<T>) return std::strong_order(l.storage_.ok_, r.storage_.ok_); else return std::strong_ordering::equivalent; } else { return std::strong_ordering::greater; } case ResultState::IsErr: if (r.is_err()) return std::strong_order(l.storage_.err_, r.storage_.err_); else return std::strong_ordering::less; case ResultState::IsMoved: break; } ::sus::unreachable_unchecked(::sus::marker::unsafe_fn); } friend constexpr auto operator<=>(const Result& l, const Result& r) noexcept requires((!VoidOrOrd<T> || !::sus::ops::Ord<E>) && VoidOrWeakOrd<T> && ::sus::ops::WeakOrd<E>) { ::sus::check(l.state_ != ResultState::IsMoved); switch (l.state_) { case ResultState::IsOk: if (r.is_ok()) { if constexpr (!std::is_void_v<T>) return std::weak_order(l.storage_.ok_, r.storage_.ok_); else return std::weak_ordering::equivalent; } else { return std::weak_ordering::greater; } case ResultState::IsErr: if (r.is_err()) return std::weak_order(l.storage_.err_, r.storage_.err_); else return std::weak_ordering::less; case ResultState::IsMoved: break; } ::sus::unreachable_unchecked(::sus::marker::unsafe_fn); } template <class U, class F> requires((!VoidOrOrd<T, U> || !::sus::ops::Ord<E, F>) && VoidOrWeakOrd<T, U> && ::sus::ops::WeakOrd<E, F>) friend constexpr auto operator<=>(const Result& l, const Result<U, F>& r) noexcept { ::sus::check(l.state_ != ResultState::IsMoved); switch (l.state_) { case ResultState::IsOk: if (r.is_ok()) { if constexpr (!std::is_void_v<T>) return std::weak_order(l.storage_.ok_, r.storage_.ok_); else return std::weak_ordering::equivalent; } else { return std::weak_ordering::greater; } case ResultState::IsErr: if (r.is_err()) return std::weak_order(l.storage_.err_, r.storage_.err_); else return std::weak_ordering::less; case ResultState::IsMoved: break; } ::sus::unreachable_unchecked(::sus::marker::unsafe_fn); } friend constexpr auto operator<=>(const Result& l, const Result& r) noexcept requires((!VoidOrWeakOrd<T> || !::sus::ops::WeakOrd<E>) && VoidOrPartialOrd<T> && ::sus::ops::PartialOrd<E>) { ::sus::check(l.state_ != ResultState::IsMoved); switch (l.state_) { case ResultState::IsOk: if (r.is_ok()) { if constexpr (!std::is_void_v<T>) return std::partial_order(l.storage_.ok_, r.storage_.ok_); else return std::partial_ordering::equivalent; } else { return std::partial_ordering::greater; } case ResultState::IsErr: if (r.is_err()) return std::partial_order(l.storage_.err_, r.storage_.err_); else return std::partial_ordering::less; case ResultState::IsMoved: break; } ::sus::unreachable_unchecked(::sus::marker::unsafe_fn); } template <class U, class F> requires((!VoidOrWeakOrd<T, U> || !::sus::ops::WeakOrd<E, F>) && VoidOrPartialOrd<T, U> && ::sus::ops::PartialOrd<E, F>) friend constexpr auto operator<=>(const Result& l, const Result<U, F>& r) noexcept { ::sus::check(l.state_ != ResultState::IsMoved); switch (l.state_) { case ResultState::IsOk: if (r.is_ok()) { if constexpr (!std::is_void_v<T>) return std::partial_order(l.storage_.ok_, r.storage_.ok_); else return std::partial_ordering::equivalent; } else { return std::partial_ordering::greater; } case ResultState::IsErr: if (r.is_err()) return std::partial_order(l.storage_.err_, r.storage_.err_); else return std::partial_ordering::less; case ResultState::IsMoved: break; } ::sus::unreachable_unchecked(::sus::marker::unsafe_fn); } template <class U, class F> requires(!VoidOrPartialOrd<T, U> || !::sus::ops::PartialOrd<E, F>) friend constexpr auto operator<=>(const Result& l, const Result<U, F>& r) noexcept = delete; private: template <class U, class V> friend class Result; template <class U> static constexpr inline decltype(auto) copy_ok_to_storage(const U& t) { if constexpr (std::is_reference_v<T>) return StoragePointer<T>(t); else return t; } template <class U> static constexpr inline decltype(auto) move_ok_to_storage(U&& t) { if constexpr (std::is_reference_v<T>) return StoragePointer<T>(t); else return ::sus::move(t); } enum WithOkType { WithOk }; constexpr inline Result(WithOkType) noexcept requires(std::is_void_v<T>) : storage_(), state_(ResultState::IsOk) {} template <std::convertible_to<T> U> constexpr inline Result(WithOkType, const U& t) noexcept : storage_(__private::kWithT, t), state_(ResultState::IsOk) {} template <std::convertible_to<T> U> constexpr inline Result(WithOkType, U&& t) noexcept requires(::sus::mem::Move<T>) : storage_(__private::kWithT, ::sus::move(t)), state_(ResultState::IsOk) {} enum WithErrType { WithErr }; constexpr inline Result(WithErrType, const E& e) noexcept : storage_(__private::kWithE, e), state_(ResultState::IsErr) {} constexpr inline Result(WithErrType, E&& e) noexcept requires(::sus::mem::Move<E>) : storage_(__private::kWithE, ::sus::move(e)), state_(ResultState::IsErr) {} struct VoidStorage {}; using OkStorageType = std::conditional_t<std::is_reference_v<T>, StoragePointer<T>, std::conditional_t<std::is_void_v<T>, VoidStorage, T>>; [[no_unique_address]] Storage<OkStorageType, E> storage_; ResultState state_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<std::remove_const_t<std::remove_reference_t<decltype(storage_.ok_)>>, std::remove_const_t<std::remove_reference_t<decltype(storage_.err_)>>, decltype(state_)>; }; using sus::iter::__private::begin; using sus::iter::__private::end; [[nodiscard]] inline constexpr auto ok() noexcept { return __private::OkVoidMarker(); } template <class T> [[nodiscard]] inline constexpr auto ok(T&& t) noexcept { return __private::OkMarker<T&&>(::sus::forward<T>(t)); } template <class E> [[nodiscard]] inline constexpr auto err(E&& e) noexcept { return __private::ErrMarker<E&&>(::sus::forward<E>(e)); } } template <class T, class E> struct sus::ops::TryImpl<::sus::result::Result<T, E>> { using Output = T; constexpr static bool is_success(const ::sus::result::Result<T, E>& t) { return t.is_ok(); } constexpr static Output into_output(::sus::result::Result<T, E> t) { return ::sus::move(t).unwrap_unchecked(::sus::marker::unsafe_fn); } constexpr static ::sus::result::Result<T, E> from_output(Output t) { return ::sus::result::Result<T, E>::with(::sus::move(t)); } }; template <class T, class E> struct sus::iter::FromIteratorImpl<::sus::result::Result<T, E>> { template <class IntoIter, int&..., class Iter = std::decay_t<decltype(std::declval<IntoIter&&>().into_iter())>, class R = typename Iter::Item, class U = ::sus::result::__private::IsResultType<R>::ok_type, class F = ::sus::result::__private::IsResultType<R>::err_type> requires(::sus::result::__private::IsResultType<R>::value && std::same_as<E, F> && ::sus::iter::IntoIterator<IntoIter, ::sus::result::Result<U, E>>) static constexpr ::sus::result::Result<T, E> from_iter( IntoIter&& result_iter) noexcept requires(!std::is_void_v<T> && !std::is_reference_v<T> && ::sus::iter::FromIterator<T, U>) { struct Unwrapper final : public ::sus::iter::IteratorBase<Unwrapper, U> { Unwrapper(Iter&& iter, Option<E>& err) : iter(iter), err(err) {} Option<U> next() noexcept { Option<::sus::result::Result<U, E>> try_item = iter.next(); if (try_item.is_none()) return Option<U>(); ::sus::result::Result<U, E> result = ::sus::move(try_item).unwrap_unchecked(::sus::marker::unsafe_fn); if (result.is_ok()) return Option<U>::with( ::sus::move(result).unwrap_unchecked(::sus::marker::unsafe_fn)); err.insert( ::sus::move(result).unwrap_err_unchecked(::sus::marker::unsafe_fn)); return Option<U>(); } ::sus::iter::SizeHint size_hint() const noexcept { return ::sus::iter::SizeHint(0u, iter.size_hint().upper); } Iter& iter; Option<E>& err; }; auto err = Option<E>(); auto iter = Unwrapper(::sus::move(result_iter).into_iter(), err); auto success_out = ::sus::result::Result<T, E>::with( ::sus::iter::from_iter<T>(::sus::move(iter))); return ::sus::move(err).map_or_else( [&]() { return ::sus::move(success_out); }, [](E e) { return ::sus::result::Result<T, E>::with_err(e); }); } }; template <class T, class E> struct std::hash<::sus::result::Result<T, E>> { auto operator()(const ::sus::result::Result<T, E>& u) const noexcept { if (u.is_ok()) return std::hash<T>()(u.as_ok()); else return std::hash<T>()(u.as_err()); } }; template <class T, class E> requires(::sus::ops::Eq<::sus::result::Result<T, E>>) struct std::equal_to<::sus::result::Result<T, E>> { constexpr auto operator()( const ::sus::result::Result<T, E>& l, const ::sus::result::Result<T, E>& r) const noexcept { return l == r; } }; namespace sus { using ::sus::result::Err; using ::sus::result::err; using ::sus::result::Ok; using ::sus::result::ok; using ::sus::result::Result; } namespace sus::num { struct i32 final { int32_t primitive_value{0}; static constexpr auto MIN_PRIMITIVE = __private::min_value<int32_t>(); static constexpr auto MAX_PRIMITIVE = __private::max_value<int32_t>(); static const i32 MIN; static const i32 MAX; static const u32 BITS; constexpr inline i32() noexcept = default; template <Signed S> requires(::sus::mem::size_of<S>() <= ::sus::mem::size_of<int32_t>()) constexpr inline i32(S v) noexcept : primitive_value(v.primitive_value) {} template <SignedPrimitiveInteger P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of<int32_t>()) constexpr inline i32(P v) noexcept : primitive_value(v) {} template <SignedPrimitiveEnum P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of<int32_t>()) constexpr inline i32(P v) noexcept : primitive_value(v) {} template <SignedPrimitiveEnumClass P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of<int32_t>()) explicit constexpr inline i32(P v) noexcept : primitive_value(static_cast<int32_t>(v)) {} template <Unsigned U> requires(::sus::mem::size_of<U>() < ::sus::mem::size_of<int32_t>()) constexpr inline i32(U v) noexcept : primitive_value(v.primitive_value) {} template <UnsignedPrimitiveInteger P> requires(::sus::mem::size_of<P>() < ::sus::mem::size_of<int32_t>()) constexpr inline i32(P v) noexcept : primitive_value(v) {} template <UnsignedPrimitiveEnum P> requires(::sus::mem::size_of<P>() < ::sus::mem::size_of<int32_t>()) constexpr inline i32(P v) noexcept : primitive_value(v) {} template <UnsignedPrimitiveEnumClass P> requires(::sus::mem::size_of<P>() < ::sus::mem::size_of<int32_t>()) explicit constexpr inline i32(P v) noexcept : primitive_value(static_cast<int32_t>(v)) {} template <Signed S> requires(::sus::mem::size_of<S>() <= ::sus::mem::size_of<int32_t>()) constexpr inline i32& operator=(S v) noexcept { primitive_value = v.primitive_value; return *this; } template <SignedPrimitiveInteger P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of<int32_t>()) constexpr inline i32& operator=(P v) noexcept { primitive_value = v; return *this; } template <SignedPrimitiveEnum P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of<int32_t>()) constexpr inline i32& operator=(P v) noexcept { primitive_value = v; return *this; } template <Signed S> requires(::sus::mem::size_of<S>() <= ::sus::mem::size_of<int32_t>()) __attribute__((pure)) static constexpr i32 from(S s) noexcept { return i32(s); } template <Signed S> __attribute__((pure)) static constexpr ::sus::result::Result<i32, ::sus::num::TryFromIntError> try_from(S s) noexcept { using R = ::sus::result::Result<i32, ::sus::num::TryFromIntError>; if constexpr (MIN_PRIMITIVE > S::MIN_PRIMITIVE) { if (s.primitive_value < MIN_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } if constexpr (MAX_PRIMITIVE < S::MAX_PRIMITIVE) { if (s.primitive_value > MAX_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(i32(static_cast<int32_t>(s.primitive_value))); } template <Unsigned U> __attribute__((pure)) static constexpr ::sus::result::Result<i32, ::sus::num::TryFromIntError> try_from(U u) noexcept { using R = ::sus::result::Result<i32, ::sus::num::TryFromIntError>; constexpr auto umax = __private::into_unsigned(MAX_PRIMITIVE); if constexpr (umax < U::MAX_PRIMITIVE) { if (u.primitive_value > umax) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(i32(static_cast<int32_t>(u.primitive_value))); } template <SignedPrimitiveInteger S> requires(::sus::mem::size_of<S>() <= ::sus::mem::size_of<int32_t>()) __attribute__((pure)) static constexpr i32 from(S s) noexcept { return i32(s); } template <SignedPrimitiveInteger S> __attribute__((pure)) static constexpr ::sus::result::Result<i32, ::sus::num::TryFromIntError> try_from(S s) noexcept { using R = ::sus::result::Result<i32, ::sus::num::TryFromIntError>; if constexpr (MIN_PRIMITIVE > __private::min_value<S>()) { if (s < MIN_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } if constexpr (MAX_PRIMITIVE < __private::max_value<S>()) { if (s > MAX_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(i32(static_cast<int32_t>(s))); } template <class S> requires((SignedPrimitiveEnum<S> || SignedPrimitiveEnumClass<S>) && ::sus::mem::size_of<S>() <= ::sus::mem::size_of<int32_t>()) __attribute__((pure)) static constexpr i32 from(S s) noexcept { using D = std::underlying_type_t<S>; return i32(static_cast<std::underlying_type_t<S>>(s)); } template <class S> requires(SignedPrimitiveEnum<S> || SignedPrimitiveEnumClass<S>) __attribute__((pure)) static constexpr ::sus::result::Result<i32, ::sus::num::TryFromIntError> try_from(S s) noexcept { using D = std::underlying_type_t<S>; using R = ::sus::result::Result<i32, ::sus::num::TryFromIntError>; if constexpr (MIN_PRIMITIVE > __private::min_value<D>()) { if (static_cast<D>(s) < MIN_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } if constexpr (MAX_PRIMITIVE < __private::max_value<D>()) { if (static_cast<D>(s) > MAX_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(i32(static_cast<int32_t>(s))); } template <UnsignedPrimitiveInteger U> __attribute__((pure)) static constexpr ::sus::result::Result<i32, ::sus::num::TryFromIntError> try_from(U u) noexcept { using R = ::sus::result::Result<i32, ::sus::num::TryFromIntError>; constexpr auto umax = __private::into_unsigned(MAX_PRIMITIVE); if constexpr (umax < __private::max_value<U>()) { if (u > umax) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(i32(static_cast<int32_t>(u))); } template <class U> requires(UnsignedPrimitiveEnum<U> || UnsignedPrimitiveEnumClass<U>) __attribute__((pure)) static constexpr ::sus::result::Result<i32, ::sus::num::TryFromIntError> try_from(U u) noexcept { using D = std::underlying_type_t<U>; using R = ::sus::result::Result<i32, ::sus::num::TryFromIntError>; constexpr auto umax = __private::into_unsigned(MAX_PRIMITIVE); if constexpr (umax < __private::max_value<D>()) { if (static_cast<D>(u) > umax) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(i32(static_cast<int32_t>(u))); } static constexpr i32 from_product( ::sus::iter::Iterator<i32> auto&& it) noexcept { auto p = i32(int32_t{1}); for (i32 i : ::sus::move(it)) p *= i; return p; } static constexpr i32 from_sum( ::sus::iter::Iterator<i32> auto&& it) noexcept { auto p = i32(int32_t{0}); for (i32 i : ::sus::move(it)) p += i; return p; } template <SignedPrimitiveInteger U> requires(::sus::mem::size_of<U>() >= ::sus::mem::size_of<int32_t>()) __attribute__((pure)) constexpr inline explicit operator U() const { return primitive_value; } __attribute__((pure)) constexpr bool is_negative() const& noexcept { return primitive_value < 0; } __attribute__((pure)) constexpr bool is_positive() const& noexcept { return primitive_value > 0; } __attribute__((pure)) constexpr i32 signum() const& noexcept { if (primitive_value < 0) return int32_t{-1}; else return int32_t{primitive_value != 0}; } [[nodiscard]] __attribute__((pure)) friend constexpr inline bool operator==( const i32& l, const i32& r) noexcept = default; template <SignedPrimitiveInteger P> [[nodiscard]] __attribute__((pure)) friend constexpr inline bool operator==( const i32& l, const P& r) noexcept { return l.primitive_value == r; } template <Signed S> [[nodiscard]] __attribute__((pure)) friend constexpr inline bool operator==( const i32& l, const S& r) noexcept { return l.primitive_value == r.primitive_value; } template <UnsignedPrimitiveInteger P> [[nodiscard]] __attribute__((pure)) friend constexpr inline std::strong_ordering operator<=>( const i32& l, const i32& r) noexcept { return l.primitive_value <=> r.primitive_value; } template <SignedPrimitiveInteger P> [[nodiscard]] __attribute__((pure)) friend constexpr inline std::strong_ordering operator<=>( const i32& l, const P& r) noexcept { return l.primitive_value <=> r; } template <Signed S> [[nodiscard]] __attribute__((pure)) friend constexpr inline std::strong_ordering operator<=>( const i32& l, const S& r) noexcept { return l.primitive_value <=> r.primitive_value; } __attribute__((pure)) constexpr inline i32 operator-() const& noexcept { ::sus::check(primitive_value != MIN_PRIMITIVE); return __private::unchecked_neg(primitive_value); } __attribute__((pure)) constexpr inline i32 operator~() const& noexcept { return __private::into_signed( __private::unchecked_not(__private::into_unsigned(primitive_value))); } [[nodiscard]] __attribute__((pure)) friend constexpr inline i32 operator+( const i32& l, const i32& r) noexcept { const auto out = __private::add_with_overflow(l.primitive_value, r.primitive_value); ::sus::check(!out.overflow); return out.value; } [[nodiscard]] __attribute__((pure)) friend constexpr inline i32 operator-( const i32& l, const i32& r) noexcept { const auto out = __private::sub_with_overflow(l.primitive_value, r.primitive_value); ::sus::check(!out.overflow); return out.value; } [[nodiscard]] __attribute__((pure)) friend constexpr inline i32 operator*( const i32& l, const i32& r) noexcept { const auto out = __private::mul_with_overflow(l.primitive_value, r.primitive_value); ::sus::check(!out.overflow); return out.value; } [[nodiscard]] __attribute__((pure)) friend constexpr inline i32 operator/( const i32& l, const i32& r) noexcept { ::sus::check(r.primitive_value != 0); ::sus::check(l.primitive_value != MIN_PRIMITIVE || r.primitive_value != -1); return static_cast<int32_t>(l.primitive_value / r.primitive_value); } [[nodiscard]] __attribute__((pure)) friend constexpr inline i32 operator%( const i32& l, const i32& r) noexcept { ::sus::check(r.primitive_value != 0); ::sus::check(l.primitive_value != MIN_PRIMITIVE || r.primitive_value != -1); return static_cast<int32_t>(l.primitive_value % r.primitive_value); } [[nodiscard]] __attribute__((pure)) friend constexpr inline i32 operator&( const i32& l, const i32& r) noexcept { return static_cast<int32_t>(l.primitive_value & r.primitive_value); } [[nodiscard]] __attribute__((pure)) friend constexpr inline i32 operator|( const i32& l, const i32& r) noexcept { return static_cast<int32_t>(l.primitive_value | r.primitive_value); } [[nodiscard]] __attribute__((pure)) friend constexpr inline i32 operator^( const i32& l, const i32& r) noexcept { return static_cast<int32_t>(l.primitive_value ^ r.primitive_value); } [[nodiscard]] __attribute__((pure)) friend constexpr inline i32 operator<<( const i32& l, const u32& r) noexcept { const auto out = __private::shl_with_overflow(l.primitive_value, r.primitive_value); ::sus::check(!out.overflow); return out.value; } [[nodiscard]] __attribute__((pure)) friend constexpr inline i32 operator>>( const i32& l, const u32& r) noexcept { const auto out = __private::shr_with_overflow(l.primitive_value, r.primitive_value); ::sus::check(!out.overflow); return out.value; } constexpr inline void operator+=(i32 r) & noexcept { const auto out = __private::add_with_overflow(primitive_value, r.primitive_value); ::sus::check(!out.overflow); primitive_value = out.value; } constexpr inline void operator-=(i32 r) & noexcept { const auto out = __private::sub_with_overflow(primitive_value, r.primitive_value); ::sus::check(!out.overflow); primitive_value = out.value; } constexpr inline void operator*=(i32 r) & noexcept { const auto out = __private::mul_with_overflow(primitive_value, r.primitive_value); ::sus::check(!out.overflow); primitive_value = out.value; } constexpr inline void operator/=(i32 r) & noexcept { ::sus::check(r.primitive_value != 0); ::sus::check(primitive_value != MIN_PRIMITIVE || r.primitive_value != -1); primitive_value /= r.primitive_value; } constexpr inline void operator%=(i32 r) & noexcept { ::sus::check(r.primitive_value != 0); ::sus::check(primitive_value != MIN_PRIMITIVE || r.primitive_value != -1); primitive_value %= r.primitive_value; } constexpr inline void operator&=(i32 r) & noexcept { primitive_value &= r.primitive_value; } constexpr inline void operator|=(i32 r) & noexcept { primitive_value |= r.primitive_value; } constexpr inline void operator^=(i32 r) & noexcept { primitive_value ^= r.primitive_value; } constexpr inline void operator<<=(const u32& r) & noexcept { const auto out = __private::shl_with_overflow(primitive_value, r.primitive_value); ::sus::check(!out.overflow); primitive_value = out.value; } constexpr inline void operator>>=(const u32& r) & noexcept { const auto out = __private::shr_with_overflow(primitive_value, r.primitive_value); ::sus::check(!out.overflow); primitive_value = out.value; } __attribute__((pure)) constexpr inline i32 abs() const& noexcept { ::sus::check(primitive_value != MIN_PRIMITIVE); if (primitive_value >= 0) return primitive_value; else return __private::unchecked_neg(primitive_value); } __attribute__((pure)) constexpr Option<i32> checked_abs() const& noexcept { if (primitive_value != MIN_PRIMITIVE) [[likely]] return Option<i32>::with(abs()); else return Option<i32>(); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i32, bool>> __attribute__((pure)) constexpr Tuple overflowing_abs() const& noexcept { if (primitive_value != MIN_PRIMITIVE) [[likely]] return Tuple::with(abs(), false); else return Tuple::with(MIN, true); } __attribute__((pure)) constexpr i32 saturating_abs() const& noexcept { if (primitive_value != MIN_PRIMITIVE) [[likely]] return abs(); else return MAX; } __attribute__((pure)) constexpr u32 unsigned_abs() const& noexcept { if (primitive_value >= 0) { return __private::into_unsigned(primitive_value); } else { const auto neg_plus_one = __private::unchecked_add(primitive_value, int32_t{1}); const auto pos_minus_one = __private::into_unsigned(__private::unchecked_neg(neg_plus_one)); return __private::unchecked_add(pos_minus_one, decltype(pos_minus_one){1}); } } __attribute__((pure)) constexpr i32 wrapping_abs() const& noexcept { if (primitive_value != MIN_PRIMITIVE) [[likely]] return abs(); else return MIN; } __attribute__((pure)) constexpr u32 abs_diff(const i32& r) const& noexcept { if (primitive_value >= r.primitive_value) { return __private::sub_with_unsigned_positive_result(primitive_value, r.primitive_value); } else { return __private::sub_with_unsigned_positive_result(r.primitive_value, primitive_value); } } __attribute__((pure)) constexpr Option<i32> checked_add(const i32& rhs) const& noexcept { const auto out = __private::add_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return Option<i32>::with(out.value); else return Option<i32>(); } __attribute__((pure)) constexpr Option<i32> checked_add_unsigned( const u32& rhs) const& noexcept { const auto out = __private::add_with_overflow_unsigned(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return Option<i32>::with(out.value); else return Option<i32>(); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i32, bool>> __attribute__((pure)) constexpr Tuple overflowing_add(const i32& rhs) const& noexcept { const auto r = __private::add_with_overflow(primitive_value, rhs.primitive_value); return Tuple::with(r.value, r.overflow); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i32, bool>> __attribute__((pure)) constexpr Tuple overflowing_add_unsigned( const u32& rhs) const& noexcept { const auto r = __private::add_with_overflow_unsigned(primitive_value, rhs.primitive_value); return Tuple::with(r.value, r.overflow); } __attribute__((pure)) constexpr i32 saturating_add(const i32& rhs) const& noexcept { return __private::saturating_add(primitive_value, rhs.primitive_value); } __attribute__((pure)) constexpr i32 saturating_add_unsigned( const u32& rhs) const& noexcept { const auto r = __private::add_with_overflow_unsigned(primitive_value, rhs.primitive_value); if (!r.overflow) [[likely]] return r.value; else return MAX; } __attribute__((pure)) inline constexpr i32 unchecked_add( ::sus::marker::UnsafeFnMarker, const i32& rhs) const& noexcept { return __private::unchecked_add(primitive_value, rhs.primitive_value); } __attribute__((pure)) constexpr i32 wrapping_add(const i32& rhs) const& noexcept { return __private::wrapping_add(primitive_value, rhs.primitive_value); } __attribute__((pure)) constexpr i32 wrapping_add_unsigned( const u32& rhs) const& noexcept { return __private::add_with_overflow_unsigned(primitive_value, rhs.primitive_value) .value; } __attribute__((pure)) constexpr Option<i32> checked_div(const i32& rhs) const& noexcept { if (__private::div_overflows(primitive_value, rhs.primitive_value)) [[unlikely]] return Option<i32>(); else return Option<i32>::with( __private::unchecked_div(primitive_value, rhs.primitive_value)); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i32, bool>> __attribute__((pure)) constexpr Tuple overflowing_div(const i32& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0); if (__private::div_overflows_nonzero(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)) [[unlikely]] { return Tuple::with(MIN, true); } else { return Tuple::with( __private::unchecked_div(primitive_value, rhs.primitive_value), false); } } __attribute__((pure)) constexpr i32 saturating_div(const i32& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0); if (__private::div_overflows_nonzero(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)) [[unlikely]] { return MAX; } else { return __private::unchecked_div(primitive_value, rhs.primitive_value); } } __attribute__((pure)) constexpr i32 wrapping_div(const i32& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0); if (__private::div_overflows_nonzero(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)) [[unlikely]] { return MIN; } else { return __private::unchecked_div(primitive_value, rhs.primitive_value); } } __attribute__((pure)) constexpr Option<i32> checked_mul(const i32& rhs) const& noexcept { const auto out = __private::mul_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return Option<i32>::with(out.value); else return Option<i32>(); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i32, bool>> __attribute__((pure)) constexpr Tuple overflowing_mul(const i32& rhs) const& noexcept { const auto out = __private::mul_with_overflow(primitive_value, rhs.primitive_value); return Tuple::with(out.value, out.overflow); } __attribute__((pure)) constexpr i32 saturating_mul(const i32& rhs) const& noexcept { return __private::saturating_mul(primitive_value, rhs.primitive_value); } __attribute__((pure)) constexpr inline i32 unchecked_mul( ::sus::marker::UnsafeFnMarker, const i32& rhs) const& noexcept { return __private::unchecked_mul(primitive_value, rhs.primitive_value); } __attribute__((pure)) constexpr i32 wrapping_mul(const i32& rhs) const& noexcept { return __private::wrapping_mul(primitive_value, rhs.primitive_value); } __attribute__((pure)) constexpr Option<i32> checked_neg() const& noexcept { if (primitive_value != MIN_PRIMITIVE) [[likely]] return Option<i32>::with(__private::unchecked_neg(primitive_value)); else return Option<i32>(); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i32, bool>> __attribute__((pure)) constexpr Tuple overflowing_neg() const& noexcept { if (primitive_value != MIN_PRIMITIVE) [[likely]] return Tuple::with(__private::unchecked_neg(primitive_value), false); else return Tuple::with(MIN, true); } __attribute__((pure)) constexpr i32 saturating_neg() const& noexcept { if (primitive_value != MIN_PRIMITIVE) [[likely]] return __private::unchecked_neg(primitive_value); else return MAX; } __attribute__((pure)) constexpr i32 wrapping_neg() const& noexcept { if (primitive_value != MIN_PRIMITIVE) [[likely]] return __private::unchecked_neg(primitive_value); else return MIN; } __attribute__((pure)) constexpr Option<i32> checked_rem(const i32& rhs) const& noexcept { if (__private::div_overflows(primitive_value, rhs.primitive_value)) [[unlikely]] return Option<i32>(); else return Option<i32>::with( static_cast<int32_t>(primitive_value % rhs.primitive_value)); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i32, bool>> __attribute__((pure)) constexpr Tuple overflowing_rem(const i32& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0); if (__private::div_overflows_nonzero(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)) [[unlikely]] { return Tuple::with(int32_t{0}, true); } else { return Tuple::with( static_cast<int32_t>(primitive_value % rhs.primitive_value), false); } } __attribute__((pure)) constexpr i32 wrapping_rem(const i32& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0); if (__private::div_overflows_nonzero(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)) [[likely]] { return int32_t{0}; } else { return static_cast<int32_t>(primitive_value % rhs.primitive_value); } } __attribute__((pure)) constexpr i32 div_euclid(const i32& rhs) const& noexcept { ::sus::check(!__private::div_overflows(primitive_value, rhs.primitive_value)); return __private::div_euclid(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value); } __attribute__((pure)) constexpr Option<i32> checked_div_euclid( const i32& rhs) const& noexcept { if (__private::div_overflows(primitive_value, rhs.primitive_value)) [[unlikely]] { return Option<i32>(); } else { return Option<i32>::with(__private::div_euclid( ::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)); } } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i32, bool>> __attribute__((pure)) constexpr Tuple overflowing_div_euclid( const i32& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0); if (__private::div_overflows_nonzero(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)) [[unlikely]] { return Tuple::with(MIN, true); } else { return Tuple::with( __private::div_euclid(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value), false); } } __attribute__((pure)) constexpr i32 wrapping_div_euclid(const i32& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0); if (__private::div_overflows_nonzero(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)) [[unlikely]] { return MIN; } else { return __private::div_euclid(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value); } } __attribute__((pure)) constexpr i32 rem_euclid(const i32& rhs) const& noexcept { ::sus::check(!__private::div_overflows(primitive_value, rhs.primitive_value)); return __private::rem_euclid(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value); } __attribute__((pure)) constexpr Option<i32> checked_rem_euclid( const i32& rhs) const& noexcept { if (__private::div_overflows(primitive_value, rhs.primitive_value)) [[unlikely]] { return Option<i32>(); } else { return Option<i32>::with(__private::rem_euclid( ::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)); } } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i32, bool>> __attribute__((pure)) constexpr Tuple overflowing_rem_euclid( const i32& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0); if (__private::div_overflows_nonzero(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)) [[unlikely]] { return Tuple::with(int32_t{0}, true); } else { return Tuple::with( __private::rem_euclid(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value), false); } } __attribute__((pure)) constexpr i32 wrapping_rem_euclid(const i32& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0); if (__private::div_overflows_nonzero(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)) [[unlikely]] { return int32_t{0}; } else { return __private::rem_euclid(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value); } } __attribute__((pure)) constexpr Option<i32> checked_shl(const u32& rhs) const& noexcept { const auto out = __private::shl_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return Option<i32>::with(out.value); else return Option<i32>(); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i32, bool>> __attribute__((pure)) constexpr Tuple overflowing_shl(const u32& rhs) const& noexcept { const auto out = __private::shl_with_overflow(primitive_value, rhs.primitive_value); return Tuple::with(out.value, out.overflow); } __attribute__((pure)) constexpr i32 wrapping_shl(const u32& rhs) const& noexcept { return __private::shl_with_overflow(primitive_value, rhs.primitive_value) .value; } __attribute__((pure)) constexpr Option<i32> checked_shr(const u32& rhs) const& noexcept { const auto out = __private::shr_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return Option<i32>::with(out.value); else return Option<i32>(); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i32, bool>> __attribute__((pure)) constexpr Tuple overflowing_shr(const u32& rhs) const& noexcept { const auto out = __private::shr_with_overflow(primitive_value, rhs.primitive_value); return Tuple::with(out.value, out.overflow); } __attribute__((pure)) constexpr i32 wrapping_shr(const u32& rhs) const& noexcept { return __private::shr_with_overflow(primitive_value, rhs.primitive_value) .value; } __attribute__((pure)) constexpr Option<i32> checked_sub(const i32& rhs) const& { const auto out = __private::sub_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return Option<i32>::with(out.value); else return Option<i32>(); } __attribute__((pure)) constexpr Option<i32> checked_sub_unsigned( const u32& rhs) const& { const auto out = __private::sub_with_overflow_unsigned(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return Option<i32>::with(out.value); else return Option<i32>(); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i32, bool>> __attribute__((pure)) constexpr Tuple overflowing_sub(const i32& rhs) const& noexcept { const auto out = __private::sub_with_overflow(primitive_value, rhs.primitive_value); return Tuple::with(out.value, out.overflow); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i32, bool>> __attribute__((pure)) constexpr Tuple overflowing_sub_unsigned( const u32& rhs) const& noexcept { const auto out = __private::sub_with_overflow_unsigned(primitive_value, rhs.primitive_value); return Tuple::with(out.value, out.overflow); } __attribute__((pure)) constexpr i32 saturating_sub(const i32& rhs) const& { return __private::saturating_sub(primitive_value, rhs.primitive_value); } __attribute__((pure)) constexpr i32 saturating_sub_unsigned(const u32& rhs) const& { const auto out = __private::sub_with_overflow_unsigned(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return out.value; else return MIN; } __attribute__((pure)) inline constexpr i32 unchecked_sub(::sus::marker::UnsafeFnMarker, const i32& rhs) const& { return static_cast<int32_t>(primitive_value - rhs.primitive_value); } constexpr i32 wrapping_sub(const i32& rhs) const& { return __private::wrapping_sub(primitive_value, rhs.primitive_value); } __attribute__((pure)) constexpr i32 wrapping_sub_unsigned(const u32& rhs) const& { return __private::sub_with_overflow_unsigned(primitive_value, rhs.primitive_value) .value; } __attribute__((pure)) constexpr u32 count_ones() const& noexcept { return __private::count_ones(__private::into_unsigned(primitive_value)); } __attribute__((pure)) constexpr u32 count_zeros() const& noexcept { return (~(*this)).count_ones(); } __attribute__((pure)) constexpr u32 leading_ones() const& noexcept { return (~(*this)).leading_zeros(); } __attribute__((pure)) constexpr u32 leading_zeros() const& noexcept { return __private::leading_zeros(__private::into_unsigned(primitive_value)); } __attribute__((pure)) constexpr u32 trailing_ones() const& noexcept { return (~(*this)).trailing_zeros(); } __attribute__((pure)) constexpr u32 trailing_zeros() const& noexcept { return __private::trailing_zeros(__private::into_unsigned(primitive_value)); } __attribute__((pure)) constexpr i32 reverse_bits() const& noexcept { return __private::into_signed( __private::reverse_bits(__private::into_unsigned(primitive_value))); } __attribute__((pure)) constexpr i32 rotate_left(const u32& n) const& noexcept { return __private::into_signed(__private::rotate_left( __private::into_unsigned(primitive_value), n.primitive_value)); } __attribute__((pure)) constexpr i32 rotate_right(const u32& n) const& noexcept { return __private::into_signed(__private::rotate_right( __private::into_unsigned(primitive_value), n.primitive_value)); } __attribute__((pure)) constexpr i32 swap_bytes() const& noexcept { return __private::into_signed( __private::swap_bytes(__private::into_unsigned(primitive_value))); } __attribute__((pure)) constexpr inline i32 pow(const u32& rhs) const& noexcept { const auto out = __private::pow_with_overflow(primitive_value, rhs.primitive_value); ::sus::check(!out.overflow); return out.value; } __attribute__((pure)) constexpr Option<i32> checked_pow(const u32& rhs) const& noexcept { const auto out = __private::pow_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return Option<i32>::with(out.value); else return Option<i32>(); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i32, bool>> __attribute__((pure)) constexpr Tuple overflowing_pow(const u32& exp) const& noexcept { const auto out = __private::pow_with_overflow(primitive_value, exp.primitive_value); return Tuple::with(out.value, out.overflow); } __attribute__((pure)) constexpr i32 wrapping_pow(const u32& exp) const& noexcept { return __private::wrapping_pow(primitive_value, exp.primitive_value); } __attribute__((pure)) constexpr Option<u32> checked_log2() const& { if (primitive_value <= 0) [[unlikely]] { return Option<u32>(); } else { uint32_t zeros = __private::leading_zeros_nonzero( ::sus::marker::unsafe_fn, __private::into_unsigned(primitive_value)); return Option<u32>::with(BITS - 1_u32 - u32(zeros)); } } __attribute__((pure)) constexpr u32 log2() const& { return checked_log2().unwrap(); } __attribute__((pure)) constexpr Option<u32> checked_log10() const& { if (primitive_value <= 0) [[unlikely]] { return Option<u32>(); } else { return Option<u32>::with(__private::int_log10::i32(primitive_value)); } } __attribute__((pure)) constexpr u32 log10() const& { return checked_log10().unwrap(); } __attribute__((pure)) constexpr Option<u32> checked_log(const i32& base) const& noexcept { if (primitive_value <= 0 || base.primitive_value <= 1) [[unlikely]] { return Option<u32>(); } else { auto n = uint32_t{0}; auto r = primitive_value; const auto b = base.primitive_value; while (r >= b) { r /= b; n += 1u; } return Option<u32>::with(n); } } __attribute__((pure)) constexpr u32 log(const i32& base) const& noexcept { return checked_log(base).unwrap(); } __attribute__((pure)) static constexpr i32 from_be(const i32& x) noexcept { if constexpr (::sus::assertions::is_big_endian()) return x; else return x.swap_bytes(); } __attribute__((pure)) static constexpr i32 from_le(const i32& x) noexcept { if constexpr (::sus::assertions::is_little_endian()) return x; else return x.swap_bytes(); } __attribute__((pure)) constexpr i32 to_be() const& noexcept { if constexpr (::sus::assertions::is_big_endian()) return *this; else return swap_bytes(); } __attribute__((pure)) constexpr i32 to_le() const& noexcept { if constexpr (::sus::assertions::is_little_endian()) return *this; else return swap_bytes(); } __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<int32_t>()> to_be_bytes() const& noexcept; __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<int32_t>()> to_le_bytes() const& noexcept; __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<int32_t>()> to_ne_bytes() const& noexcept; __attribute__((pure)) static constexpr i32 from_be_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<int32_t>()>& bytes) noexcept; __attribute__((pure)) static constexpr i32 from_le_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<int32_t>()>& bytes) noexcept; __attribute__((pure)) static constexpr i32 from_ne_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<int32_t>()>& bytes) noexcept; }; inline constexpr i32 i32::MIN = i32(i32::MIN_PRIMITIVE); inline constexpr i32 i32::MAX = i32(i32::MAX_PRIMITIVE); inline constexpr u32 i32::BITS = u32(__private::num_bits<int32_t>()); struct i8 final { int8_t primitive_value{0}; static constexpr auto MIN_PRIMITIVE = __private::min_value<int8_t>(); static constexpr auto MAX_PRIMITIVE = __private::max_value<int8_t>(); static const i8 MIN; static const i8 MAX; static const u32 BITS; constexpr inline i8() noexcept = default; template <Signed S> requires(::sus::mem::size_of<S>() <= ::sus::mem::size_of<int8_t>()) constexpr inline i8(S v) noexcept : primitive_value(v.primitive_value) {} template <SignedPrimitiveInteger P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of<int8_t>()) constexpr inline i8(P v) noexcept : primitive_value(v) {} template <SignedPrimitiveEnum P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of<int8_t>()) constexpr inline i8(P v) noexcept : primitive_value(v) {} template <SignedPrimitiveEnumClass P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of<int8_t>()) explicit constexpr inline i8(P v) noexcept : primitive_value(static_cast<int8_t>(v)) {} template <Unsigned U> requires(::sus::mem::size_of<U>() < ::sus::mem::size_of<int8_t>()) constexpr inline i8(U v) noexcept : primitive_value(v.primitive_value) {} template <UnsignedPrimitiveInteger P> requires(::sus::mem::size_of<P>() < ::sus::mem::size_of<int8_t>()) constexpr inline i8(P v) noexcept : primitive_value(v) {} template <UnsignedPrimitiveEnum P> requires(::sus::mem::size_of<P>() < ::sus::mem::size_of<int8_t>()) constexpr inline i8(P v) noexcept : primitive_value(v) {} template <UnsignedPrimitiveEnumClass P> requires(::sus::mem::size_of<P>() < ::sus::mem::size_of<int8_t>()) explicit constexpr inline i8(P v) noexcept : primitive_value(static_cast<int8_t>(v)) {} template <Signed S> requires(::sus::mem::size_of<S>() <= ::sus::mem::size_of<int8_t>()) constexpr inline i8& operator=(S v) noexcept { primitive_value = v.primitive_value; return *this; } template <SignedPrimitiveInteger P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of<int8_t>()) constexpr inline i8& operator=(P v) noexcept { primitive_value = v; return *this; } template <SignedPrimitiveEnum P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of<int8_t>()) constexpr inline i8& operator=(P v) noexcept { primitive_value = v; return *this; } template <Signed S> requires(::sus::mem::size_of<S>() <= ::sus::mem::size_of<int8_t>()) __attribute__((pure)) static constexpr i8 from(S s) noexcept { return i8(s); } template <Signed S> __attribute__((pure)) static constexpr ::sus::result::Result<i8, ::sus::num::TryFromIntError> try_from(S s) noexcept { using R = ::sus::result::Result<i8, ::sus::num::TryFromIntError>; if constexpr (MIN_PRIMITIVE > S::MIN_PRIMITIVE) { if (s.primitive_value < MIN_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } if constexpr (MAX_PRIMITIVE < S::MAX_PRIMITIVE) { if (s.primitive_value > MAX_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(i8(static_cast<int8_t>(s.primitive_value))); } template <Unsigned U> __attribute__((pure)) static constexpr ::sus::result::Result<i8, ::sus::num::TryFromIntError> try_from(U u) noexcept { using R = ::sus::result::Result<i8, ::sus::num::TryFromIntError>; constexpr auto umax = __private::into_unsigned(MAX_PRIMITIVE); if constexpr (umax < U::MAX_PRIMITIVE) { if (u.primitive_value > umax) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(i8(static_cast<int8_t>(u.primitive_value))); } template <SignedPrimitiveInteger S> requires(::sus::mem::size_of<S>() <= ::sus::mem::size_of<int8_t>()) __attribute__((pure)) static constexpr i8 from(S s) noexcept { return i8(s); } template <SignedPrimitiveInteger S> __attribute__((pure)) static constexpr ::sus::result::Result<i8, ::sus::num::TryFromIntError> try_from(S s) noexcept { using R = ::sus::result::Result<i8, ::sus::num::TryFromIntError>; if constexpr (MIN_PRIMITIVE > __private::min_value<S>()) { if (s < MIN_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } if constexpr (MAX_PRIMITIVE < __private::max_value<S>()) { if (s > MAX_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(i8(static_cast<int8_t>(s))); } template <class S> requires((SignedPrimitiveEnum<S> || SignedPrimitiveEnumClass<S>) && ::sus::mem::size_of<S>() <= ::sus::mem::size_of<int8_t>()) __attribute__((pure)) static constexpr i8 from(S s) noexcept { using D = std::underlying_type_t<S>; return i8(static_cast<std::underlying_type_t<S>>(s)); } template <class S> requires(SignedPrimitiveEnum<S> || SignedPrimitiveEnumClass<S>) __attribute__((pure)) static constexpr ::sus::result::Result<i8, ::sus::num::TryFromIntError> try_from(S s) noexcept { using D = std::underlying_type_t<S>; using R = ::sus::result::Result<i8, ::sus::num::TryFromIntError>; if constexpr (MIN_PRIMITIVE > __private::min_value<D>()) { if (static_cast<D>(s) < MIN_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } if constexpr (MAX_PRIMITIVE < __private::max_value<D>()) { if (static_cast<D>(s) > MAX_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(i8(static_cast<int8_t>(s))); } template <UnsignedPrimitiveInteger U> __attribute__((pure)) static constexpr ::sus::result::Result<i8, ::sus::num::TryFromIntError> try_from(U u) noexcept { using R = ::sus::result::Result<i8, ::sus::num::TryFromIntError>; constexpr auto umax = __private::into_unsigned(MAX_PRIMITIVE); if constexpr (umax < __private::max_value<U>()) { if (u > umax) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(i8(static_cast<int8_t>(u))); } template <class U> requires(UnsignedPrimitiveEnum<U> || UnsignedPrimitiveEnumClass<U>) __attribute__((pure)) static constexpr ::sus::result::Result<i8, ::sus::num::TryFromIntError> try_from(U u) noexcept { using D = std::underlying_type_t<U>; using R = ::sus::result::Result<i8, ::sus::num::TryFromIntError>; constexpr auto umax = __private::into_unsigned(MAX_PRIMITIVE); if constexpr (umax < __private::max_value<D>()) { if (static_cast<D>(u) > umax) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(i8(static_cast<int8_t>(u))); } static constexpr i8 from_product( ::sus::iter::Iterator<i8> auto&& it) noexcept { auto p = i8(int8_t{1}); for (i8 i : ::sus::move(it)) p *= i; return p; } static constexpr i8 from_sum( ::sus::iter::Iterator<i8> auto&& it) noexcept { auto p = i8(int8_t{0}); for (i8 i : ::sus::move(it)) p += i; return p; } template <SignedPrimitiveInteger U> requires(::sus::mem::size_of<U>() >= ::sus::mem::size_of<int8_t>()) __attribute__((pure)) constexpr inline explicit operator U() const { return primitive_value; } __attribute__((pure)) constexpr bool is_negative() const& noexcept { return primitive_value < 0; } __attribute__((pure)) constexpr bool is_positive() const& noexcept { return primitive_value > 0; } __attribute__((pure)) constexpr i8 signum() const& noexcept { if (primitive_value < 0) return int8_t{-1}; else return int8_t{primitive_value != 0}; } [[nodiscard]] __attribute__((pure)) friend constexpr inline bool operator==( const i8& l, const i8& r) noexcept = default; template <SignedPrimitiveInteger P> [[nodiscard]] __attribute__((pure)) friend constexpr inline bool operator==( const i8& l, const P& r) noexcept { return l.primitive_value == r; } template <Signed S> [[nodiscard]] __attribute__((pure)) friend constexpr inline bool operator==( const i8& l, const S& r) noexcept { return l.primitive_value == r.primitive_value; } template <UnsignedPrimitiveInteger P> [[nodiscard]] __attribute__((pure)) friend constexpr inline std::strong_ordering operator<=>( const i8& l, const i8& r) noexcept { return l.primitive_value <=> r.primitive_value; } template <SignedPrimitiveInteger P> [[nodiscard]] __attribute__((pure)) friend constexpr inline std::strong_ordering operator<=>( const i8& l, const P& r) noexcept { return l.primitive_value <=> r; } template <Signed S> [[nodiscard]] __attribute__((pure)) friend constexpr inline std::strong_ordering operator<=>( const i8& l, const S& r) noexcept { return l.primitive_value <=> r.primitive_value; } __attribute__((pure)) constexpr inline i8 operator-() const& noexcept { ::sus::check(primitive_value != MIN_PRIMITIVE); return __private::unchecked_neg(primitive_value); } __attribute__((pure)) constexpr inline i8 operator~() const& noexcept { return __private::into_signed( __private::unchecked_not(__private::into_unsigned(primitive_value))); } [[nodiscard]] __attribute__((pure)) friend constexpr inline i8 operator+( const i8& l, const i8& r) noexcept { const auto out = __private::add_with_overflow(l.primitive_value, r.primitive_value); ::sus::check(!out.overflow); return out.value; } [[nodiscard]] __attribute__((pure)) friend constexpr inline i8 operator-( const i8& l, const i8& r) noexcept { const auto out = __private::sub_with_overflow(l.primitive_value, r.primitive_value); ::sus::check(!out.overflow); return out.value; } [[nodiscard]] __attribute__((pure)) friend constexpr inline i8 operator*( const i8& l, const i8& r) noexcept { const auto out = __private::mul_with_overflow(l.primitive_value, r.primitive_value); ::sus::check(!out.overflow); return out.value; } [[nodiscard]] __attribute__((pure)) friend constexpr inline i8 operator/( const i8& l, const i8& r) noexcept { ::sus::check(r.primitive_value != 0); ::sus::check(l.primitive_value != MIN_PRIMITIVE || r.primitive_value != -1); return static_cast<int8_t>(l.primitive_value / r.primitive_value); } [[nodiscard]] __attribute__((pure)) friend constexpr inline i8 operator%( const i8& l, const i8& r) noexcept { ::sus::check(r.primitive_value != 0); ::sus::check(l.primitive_value != MIN_PRIMITIVE || r.primitive_value != -1); return static_cast<int8_t>(l.primitive_value % r.primitive_value); } [[nodiscard]] __attribute__((pure)) friend constexpr inline i8 operator&( const i8& l, const i8& r) noexcept { return static_cast<int8_t>(l.primitive_value & r.primitive_value); } [[nodiscard]] __attribute__((pure)) friend constexpr inline i8 operator|( const i8& l, const i8& r) noexcept { return static_cast<int8_t>(l.primitive_value | r.primitive_value); } [[nodiscard]] __attribute__((pure)) friend constexpr inline i8 operator^( const i8& l, const i8& r) noexcept { return static_cast<int8_t>(l.primitive_value ^ r.primitive_value); } [[nodiscard]] __attribute__((pure)) friend constexpr inline i8 operator<<( const i8& l, const u32& r) noexcept { const auto out = __private::shl_with_overflow(l.primitive_value, r.primitive_value); ::sus::check(!out.overflow); return out.value; } [[nodiscard]] __attribute__((pure)) friend constexpr inline i8 operator>>( const i8& l, const u32& r) noexcept { const auto out = __private::shr_with_overflow(l.primitive_value, r.primitive_value); ::sus::check(!out.overflow); return out.value; } constexpr inline void operator+=(i8 r) & noexcept { const auto out = __private::add_with_overflow(primitive_value, r.primitive_value); ::sus::check(!out.overflow); primitive_value = out.value; } constexpr inline void operator-=(i8 r) & noexcept { const auto out = __private::sub_with_overflow(primitive_value, r.primitive_value); ::sus::check(!out.overflow); primitive_value = out.value; } constexpr inline void operator*=(i8 r) & noexcept { const auto out = __private::mul_with_overflow(primitive_value, r.primitive_value); ::sus::check(!out.overflow); primitive_value = out.value; } constexpr inline void operator/=(i8 r) & noexcept { ::sus::check(r.primitive_value != 0); ::sus::check(primitive_value != MIN_PRIMITIVE || r.primitive_value != -1); primitive_value /= r.primitive_value; } constexpr inline void operator%=(i8 r) & noexcept { ::sus::check(r.primitive_value != 0); ::sus::check(primitive_value != MIN_PRIMITIVE || r.primitive_value != -1); primitive_value %= r.primitive_value; } constexpr inline void operator&=(i8 r) & noexcept { primitive_value &= r.primitive_value; } constexpr inline void operator|=(i8 r) & noexcept { primitive_value |= r.primitive_value; } constexpr inline void operator^=(i8 r) & noexcept { primitive_value ^= r.primitive_value; } constexpr inline void operator<<=(const u32& r) & noexcept { const auto out = __private::shl_with_overflow(primitive_value, r.primitive_value); ::sus::check(!out.overflow); primitive_value = out.value; } constexpr inline void operator>>=(const u32& r) & noexcept { const auto out = __private::shr_with_overflow(primitive_value, r.primitive_value); ::sus::check(!out.overflow); primitive_value = out.value; } __attribute__((pure)) constexpr inline i8 abs() const& noexcept { ::sus::check(primitive_value != MIN_PRIMITIVE); if (primitive_value >= 0) return primitive_value; else return __private::unchecked_neg(primitive_value); } __attribute__((pure)) constexpr Option<i8> checked_abs() const& noexcept { if (primitive_value != MIN_PRIMITIVE) [[likely]] return Option<i8>::with(abs()); else return Option<i8>(); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i8, bool>> __attribute__((pure)) constexpr Tuple overflowing_abs() const& noexcept { if (primitive_value != MIN_PRIMITIVE) [[likely]] return Tuple::with(abs(), false); else return Tuple::with(MIN, true); } __attribute__((pure)) constexpr i8 saturating_abs() const& noexcept { if (primitive_value != MIN_PRIMITIVE) [[likely]] return abs(); else return MAX; } __attribute__((pure)) constexpr u8 unsigned_abs() const& noexcept { if (primitive_value >= 0) { return __private::into_unsigned(primitive_value); } else { const auto neg_plus_one = __private::unchecked_add(primitive_value, int8_t{1}); const auto pos_minus_one = __private::into_unsigned(__private::unchecked_neg(neg_plus_one)); return __private::unchecked_add(pos_minus_one, decltype(pos_minus_one){1}); } } __attribute__((pure)) constexpr i8 wrapping_abs() const& noexcept { if (primitive_value != MIN_PRIMITIVE) [[likely]] return abs(); else return MIN; } __attribute__((pure)) constexpr u8 abs_diff(const i8& r) const& noexcept { if (primitive_value >= r.primitive_value) { return __private::sub_with_unsigned_positive_result(primitive_value, r.primitive_value); } else { return __private::sub_with_unsigned_positive_result(r.primitive_value, primitive_value); } } __attribute__((pure)) constexpr Option<i8> checked_add(const i8& rhs) const& noexcept { const auto out = __private::add_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return Option<i8>::with(out.value); else return Option<i8>(); } __attribute__((pure)) constexpr Option<i8> checked_add_unsigned( const u8& rhs) const& noexcept { const auto out = __private::add_with_overflow_unsigned(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return Option<i8>::with(out.value); else return Option<i8>(); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i8, bool>> __attribute__((pure)) constexpr Tuple overflowing_add(const i8& rhs) const& noexcept { const auto r = __private::add_with_overflow(primitive_value, rhs.primitive_value); return Tuple::with(r.value, r.overflow); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i8, bool>> __attribute__((pure)) constexpr Tuple overflowing_add_unsigned( const u8& rhs) const& noexcept { const auto r = __private::add_with_overflow_unsigned(primitive_value, rhs.primitive_value); return Tuple::with(r.value, r.overflow); } __attribute__((pure)) constexpr i8 saturating_add(const i8& rhs) const& noexcept { return __private::saturating_add(primitive_value, rhs.primitive_value); } __attribute__((pure)) constexpr i8 saturating_add_unsigned( const u8& rhs) const& noexcept { const auto r = __private::add_with_overflow_unsigned(primitive_value, rhs.primitive_value); if (!r.overflow) [[likely]] return r.value; else return MAX; } __attribute__((pure)) inline constexpr i8 unchecked_add( ::sus::marker::UnsafeFnMarker, const i8& rhs) const& noexcept { return __private::unchecked_add(primitive_value, rhs.primitive_value); } __attribute__((pure)) constexpr i8 wrapping_add(const i8& rhs) const& noexcept { return __private::wrapping_add(primitive_value, rhs.primitive_value); } __attribute__((pure)) constexpr i8 wrapping_add_unsigned( const u8& rhs) const& noexcept { return __private::add_with_overflow_unsigned(primitive_value, rhs.primitive_value) .value; } __attribute__((pure)) constexpr Option<i8> checked_div(const i8& rhs) const& noexcept { if (__private::div_overflows(primitive_value, rhs.primitive_value)) [[unlikely]] return Option<i8>(); else return Option<i8>::with( __private::unchecked_div(primitive_value, rhs.primitive_value)); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i8, bool>> __attribute__((pure)) constexpr Tuple overflowing_div(const i8& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0); if (__private::div_overflows_nonzero(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)) [[unlikely]] { return Tuple::with(MIN, true); } else { return Tuple::with( __private::unchecked_div(primitive_value, rhs.primitive_value), false); } } __attribute__((pure)) constexpr i8 saturating_div(const i8& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0); if (__private::div_overflows_nonzero(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)) [[unlikely]] { return MAX; } else { return __private::unchecked_div(primitive_value, rhs.primitive_value); } } __attribute__((pure)) constexpr i8 wrapping_div(const i8& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0); if (__private::div_overflows_nonzero(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)) [[unlikely]] { return MIN; } else { return __private::unchecked_div(primitive_value, rhs.primitive_value); } } __attribute__((pure)) constexpr Option<i8> checked_mul(const i8& rhs) const& noexcept { const auto out = __private::mul_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return Option<i8>::with(out.value); else return Option<i8>(); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i8, bool>> __attribute__((pure)) constexpr Tuple overflowing_mul(const i8& rhs) const& noexcept { const auto out = __private::mul_with_overflow(primitive_value, rhs.primitive_value); return Tuple::with(out.value, out.overflow); } __attribute__((pure)) constexpr i8 saturating_mul(const i8& rhs) const& noexcept { return __private::saturating_mul(primitive_value, rhs.primitive_value); } __attribute__((pure)) constexpr inline i8 unchecked_mul( ::sus::marker::UnsafeFnMarker, const i8& rhs) const& noexcept { return __private::unchecked_mul(primitive_value, rhs.primitive_value); } __attribute__((pure)) constexpr i8 wrapping_mul(const i8& rhs) const& noexcept { return __private::wrapping_mul(primitive_value, rhs.primitive_value); } __attribute__((pure)) constexpr Option<i8> checked_neg() const& noexcept { if (primitive_value != MIN_PRIMITIVE) [[likely]] return Option<i8>::with(__private::unchecked_neg(primitive_value)); else return Option<i8>(); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i8, bool>> __attribute__((pure)) constexpr Tuple overflowing_neg() const& noexcept { if (primitive_value != MIN_PRIMITIVE) [[likely]] return Tuple::with(__private::unchecked_neg(primitive_value), false); else return Tuple::with(MIN, true); } __attribute__((pure)) constexpr i8 saturating_neg() const& noexcept { if (primitive_value != MIN_PRIMITIVE) [[likely]] return __private::unchecked_neg(primitive_value); else return MAX; } __attribute__((pure)) constexpr i8 wrapping_neg() const& noexcept { if (primitive_value != MIN_PRIMITIVE) [[likely]] return __private::unchecked_neg(primitive_value); else return MIN; } __attribute__((pure)) constexpr Option<i8> checked_rem(const i8& rhs) const& noexcept { if (__private::div_overflows(primitive_value, rhs.primitive_value)) [[unlikely]] return Option<i8>(); else return Option<i8>::with( static_cast<int8_t>(primitive_value % rhs.primitive_value)); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i8, bool>> __attribute__((pure)) constexpr Tuple overflowing_rem(const i8& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0); if (__private::div_overflows_nonzero(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)) [[unlikely]] { return Tuple::with(int8_t{0}, true); } else { return Tuple::with( static_cast<int8_t>(primitive_value % rhs.primitive_value), false); } } __attribute__((pure)) constexpr i8 wrapping_rem(const i8& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0); if (__private::div_overflows_nonzero(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)) [[likely]] { return int8_t{0}; } else { return static_cast<int8_t>(primitive_value % rhs.primitive_value); } } __attribute__((pure)) constexpr i8 div_euclid(const i8& rhs) const& noexcept { ::sus::check(!__private::div_overflows(primitive_value, rhs.primitive_value)); return __private::div_euclid(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value); } __attribute__((pure)) constexpr Option<i8> checked_div_euclid( const i8& rhs) const& noexcept { if (__private::div_overflows(primitive_value, rhs.primitive_value)) [[unlikely]] { return Option<i8>(); } else { return Option<i8>::with(__private::div_euclid( ::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)); } } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i8, bool>> __attribute__((pure)) constexpr Tuple overflowing_div_euclid( const i8& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0); if (__private::div_overflows_nonzero(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)) [[unlikely]] { return Tuple::with(MIN, true); } else { return Tuple::with( __private::div_euclid(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value), false); } } __attribute__((pure)) constexpr i8 wrapping_div_euclid(const i8& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0); if (__private::div_overflows_nonzero(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)) [[unlikely]] { return MIN; } else { return __private::div_euclid(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value); } } __attribute__((pure)) constexpr i8 rem_euclid(const i8& rhs) const& noexcept { ::sus::check(!__private::div_overflows(primitive_value, rhs.primitive_value)); return __private::rem_euclid(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value); } __attribute__((pure)) constexpr Option<i8> checked_rem_euclid( const i8& rhs) const& noexcept { if (__private::div_overflows(primitive_value, rhs.primitive_value)) [[unlikely]] { return Option<i8>(); } else { return Option<i8>::with(__private::rem_euclid( ::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)); } } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i8, bool>> __attribute__((pure)) constexpr Tuple overflowing_rem_euclid( const i8& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0); if (__private::div_overflows_nonzero(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)) [[unlikely]] { return Tuple::with(int8_t{0}, true); } else { return Tuple::with( __private::rem_euclid(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value), false); } } __attribute__((pure)) constexpr i8 wrapping_rem_euclid(const i8& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0); if (__private::div_overflows_nonzero(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)) [[unlikely]] { return int8_t{0}; } else { return __private::rem_euclid(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value); } } __attribute__((pure)) constexpr Option<i8> checked_shl(const u32& rhs) const& noexcept { const auto out = __private::shl_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return Option<i8>::with(out.value); else return Option<i8>(); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i8, bool>> __attribute__((pure)) constexpr Tuple overflowing_shl(const u32& rhs) const& noexcept { const auto out = __private::shl_with_overflow(primitive_value, rhs.primitive_value); return Tuple::with(out.value, out.overflow); } __attribute__((pure)) constexpr i8 wrapping_shl(const u32& rhs) const& noexcept { return __private::shl_with_overflow(primitive_value, rhs.primitive_value) .value; } __attribute__((pure)) constexpr Option<i8> checked_shr(const u32& rhs) const& noexcept { const auto out = __private::shr_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return Option<i8>::with(out.value); else return Option<i8>(); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i8, bool>> __attribute__((pure)) constexpr Tuple overflowing_shr(const u32& rhs) const& noexcept { const auto out = __private::shr_with_overflow(primitive_value, rhs.primitive_value); return Tuple::with(out.value, out.overflow); } __attribute__((pure)) constexpr i8 wrapping_shr(const u32& rhs) const& noexcept { return __private::shr_with_overflow(primitive_value, rhs.primitive_value) .value; } __attribute__((pure)) constexpr Option<i8> checked_sub(const i8& rhs) const& { const auto out = __private::sub_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return Option<i8>::with(out.value); else return Option<i8>(); } __attribute__((pure)) constexpr Option<i8> checked_sub_unsigned( const u8& rhs) const& { const auto out = __private::sub_with_overflow_unsigned(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return Option<i8>::with(out.value); else return Option<i8>(); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i8, bool>> __attribute__((pure)) constexpr Tuple overflowing_sub(const i8& rhs) const& noexcept { const auto out = __private::sub_with_overflow(primitive_value, rhs.primitive_value); return Tuple::with(out.value, out.overflow); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i8, bool>> __attribute__((pure)) constexpr Tuple overflowing_sub_unsigned( const u8& rhs) const& noexcept { const auto out = __private::sub_with_overflow_unsigned(primitive_value, rhs.primitive_value); return Tuple::with(out.value, out.overflow); } __attribute__((pure)) constexpr i8 saturating_sub(const i8& rhs) const& { return __private::saturating_sub(primitive_value, rhs.primitive_value); } __attribute__((pure)) constexpr i8 saturating_sub_unsigned(const u8& rhs) const& { const auto out = __private::sub_with_overflow_unsigned(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return out.value; else return MIN; } __attribute__((pure)) inline constexpr i8 unchecked_sub(::sus::marker::UnsafeFnMarker, const i8& rhs) const& { return static_cast<int8_t>(primitive_value - rhs.primitive_value); } constexpr i8 wrapping_sub(const i8& rhs) const& { return __private::wrapping_sub(primitive_value, rhs.primitive_value); } __attribute__((pure)) constexpr i8 wrapping_sub_unsigned(const u8& rhs) const& { return __private::sub_with_overflow_unsigned(primitive_value, rhs.primitive_value) .value; } __attribute__((pure)) constexpr u32 count_ones() const& noexcept { return __private::count_ones(__private::into_unsigned(primitive_value)); } __attribute__((pure)) constexpr u32 count_zeros() const& noexcept { return (~(*this)).count_ones(); } __attribute__((pure)) constexpr u32 leading_ones() const& noexcept { return (~(*this)).leading_zeros(); } __attribute__((pure)) constexpr u32 leading_zeros() const& noexcept { return __private::leading_zeros(__private::into_unsigned(primitive_value)); } __attribute__((pure)) constexpr u32 trailing_ones() const& noexcept { return (~(*this)).trailing_zeros(); } __attribute__((pure)) constexpr u32 trailing_zeros() const& noexcept { return __private::trailing_zeros(__private::into_unsigned(primitive_value)); } __attribute__((pure)) constexpr i8 reverse_bits() const& noexcept { return __private::into_signed( __private::reverse_bits(__private::into_unsigned(primitive_value))); } __attribute__((pure)) constexpr i8 rotate_left(const u32& n) const& noexcept { return __private::into_signed(__private::rotate_left( __private::into_unsigned(primitive_value), n.primitive_value)); } __attribute__((pure)) constexpr i8 rotate_right(const u32& n) const& noexcept { return __private::into_signed(__private::rotate_right( __private::into_unsigned(primitive_value), n.primitive_value)); } __attribute__((pure)) constexpr i8 swap_bytes() const& noexcept { return __private::into_signed( __private::swap_bytes(__private::into_unsigned(primitive_value))); } __attribute__((pure)) constexpr inline i8 pow(const u32& rhs) const& noexcept { const auto out = __private::pow_with_overflow(primitive_value, rhs.primitive_value); ::sus::check(!out.overflow); return out.value; } __attribute__((pure)) constexpr Option<i8> checked_pow(const u32& rhs) const& noexcept { const auto out = __private::pow_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return Option<i8>::with(out.value); else return Option<i8>(); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i8, bool>> __attribute__((pure)) constexpr Tuple overflowing_pow(const u32& exp) const& noexcept { const auto out = __private::pow_with_overflow(primitive_value, exp.primitive_value); return Tuple::with(out.value, out.overflow); } __attribute__((pure)) constexpr i8 wrapping_pow(const u32& exp) const& noexcept { return __private::wrapping_pow(primitive_value, exp.primitive_value); } __attribute__((pure)) constexpr Option<u32> checked_log2() const& { if (primitive_value <= 0) [[unlikely]] { return Option<u32>(); } else { uint32_t zeros = __private::leading_zeros_nonzero( ::sus::marker::unsafe_fn, __private::into_unsigned(primitive_value)); return Option<u32>::with(BITS - 1_u32 - u32(zeros)); } } __attribute__((pure)) constexpr u32 log2() const& { return checked_log2().unwrap(); } __attribute__((pure)) constexpr Option<u32> checked_log10() const& { if (primitive_value <= 0) [[unlikely]] { return Option<u32>(); } else { return Option<u32>::with(__private::int_log10::i8(primitive_value)); } } __attribute__((pure)) constexpr u32 log10() const& { return checked_log10().unwrap(); } __attribute__((pure)) constexpr Option<u32> checked_log(const i8& base) const& noexcept { if (primitive_value <= 0 || base.primitive_value <= 1) [[unlikely]] { return Option<u32>(); } else { auto n = uint32_t{0}; auto r = primitive_value; const auto b = base.primitive_value; while (r >= b) { r /= b; n += 1u; } return Option<u32>::with(n); } } __attribute__((pure)) constexpr u32 log(const i8& base) const& noexcept { return checked_log(base).unwrap(); } __attribute__((pure)) static constexpr i8 from_be(const i8& x) noexcept { if constexpr (::sus::assertions::is_big_endian()) return x; else return x.swap_bytes(); } __attribute__((pure)) static constexpr i8 from_le(const i8& x) noexcept { if constexpr (::sus::assertions::is_little_endian()) return x; else return x.swap_bytes(); } __attribute__((pure)) constexpr i8 to_be() const& noexcept { if constexpr (::sus::assertions::is_big_endian()) return *this; else return swap_bytes(); } __attribute__((pure)) constexpr i8 to_le() const& noexcept { if constexpr (::sus::assertions::is_little_endian()) return *this; else return swap_bytes(); } __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<int8_t>()> to_be_bytes() const& noexcept; __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<int8_t>()> to_le_bytes() const& noexcept; __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<int8_t>()> to_ne_bytes() const& noexcept; __attribute__((pure)) static constexpr i8 from_be_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<int8_t>()>& bytes) noexcept; __attribute__((pure)) static constexpr i8 from_le_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<int8_t>()>& bytes) noexcept; __attribute__((pure)) static constexpr i8 from_ne_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<int8_t>()>& bytes) noexcept; }; inline constexpr i8 i8::MIN = i8(i8::MIN_PRIMITIVE); inline constexpr i8 i8::MAX = i8(i8::MAX_PRIMITIVE); inline constexpr u32 i8::BITS = u32(__private::num_bits<int8_t>()); struct i16 final { int16_t primitive_value{0}; static constexpr auto MIN_PRIMITIVE = __private::min_value<int16_t>(); static constexpr auto MAX_PRIMITIVE = __private::max_value<int16_t>(); static const i16 MIN; static const i16 MAX; static const u32 BITS; constexpr inline i16() noexcept = default; template <Signed S> requires(::sus::mem::size_of<S>() <= ::sus::mem::size_of<int16_t>()) constexpr inline i16(S v) noexcept : primitive_value(v.primitive_value) {} template <SignedPrimitiveInteger P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of<int16_t>()) constexpr inline i16(P v) noexcept : primitive_value(v) {} template <SignedPrimitiveEnum P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of<int16_t>()) constexpr inline i16(P v) noexcept : primitive_value(v) {} template <SignedPrimitiveEnumClass P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of<int16_t>()) explicit constexpr inline i16(P v) noexcept : primitive_value(static_cast<int16_t>(v)) {} template <Unsigned U> requires(::sus::mem::size_of<U>() < ::sus::mem::size_of<int16_t>()) constexpr inline i16(U v) noexcept : primitive_value(v.primitive_value) {} template <UnsignedPrimitiveInteger P> requires(::sus::mem::size_of<P>() < ::sus::mem::size_of<int16_t>()) constexpr inline i16(P v) noexcept : primitive_value(v) {} template <UnsignedPrimitiveEnum P> requires(::sus::mem::size_of<P>() < ::sus::mem::size_of<int16_t>()) constexpr inline i16(P v) noexcept : primitive_value(v) {} template <UnsignedPrimitiveEnumClass P> requires(::sus::mem::size_of<P>() < ::sus::mem::size_of<int16_t>()) explicit constexpr inline i16(P v) noexcept : primitive_value(static_cast<int16_t>(v)) {} template <Signed S> requires(::sus::mem::size_of<S>() <= ::sus::mem::size_of<int16_t>()) constexpr inline i16& operator=(S v) noexcept { primitive_value = v.primitive_value; return *this; } template <SignedPrimitiveInteger P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of<int16_t>()) constexpr inline i16& operator=(P v) noexcept { primitive_value = v; return *this; } template <SignedPrimitiveEnum P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of<int16_t>()) constexpr inline i16& operator=(P v) noexcept { primitive_value = v; return *this; } template <Signed S> requires(::sus::mem::size_of<S>() <= ::sus::mem::size_of<int16_t>()) __attribute__((pure)) static constexpr i16 from(S s) noexcept { return i16(s); } template <Signed S> __attribute__((pure)) static constexpr ::sus::result::Result<i16, ::sus::num::TryFromIntError> try_from(S s) noexcept { using R = ::sus::result::Result<i16, ::sus::num::TryFromIntError>; if constexpr (MIN_PRIMITIVE > S::MIN_PRIMITIVE) { if (s.primitive_value < MIN_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } if constexpr (MAX_PRIMITIVE < S::MAX_PRIMITIVE) { if (s.primitive_value > MAX_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(i16(static_cast<int16_t>(s.primitive_value))); } template <Unsigned U> __attribute__((pure)) static constexpr ::sus::result::Result<i16, ::sus::num::TryFromIntError> try_from(U u) noexcept { using R = ::sus::result::Result<i16, ::sus::num::TryFromIntError>; constexpr auto umax = __private::into_unsigned(MAX_PRIMITIVE); if constexpr (umax < U::MAX_PRIMITIVE) { if (u.primitive_value > umax) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(i16(static_cast<int16_t>(u.primitive_value))); } template <SignedPrimitiveInteger S> requires(::sus::mem::size_of<S>() <= ::sus::mem::size_of<int16_t>()) __attribute__((pure)) static constexpr i16 from(S s) noexcept { return i16(s); } template <SignedPrimitiveInteger S> __attribute__((pure)) static constexpr ::sus::result::Result<i16, ::sus::num::TryFromIntError> try_from(S s) noexcept { using R = ::sus::result::Result<i16, ::sus::num::TryFromIntError>; if constexpr (MIN_PRIMITIVE > __private::min_value<S>()) { if (s < MIN_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } if constexpr (MAX_PRIMITIVE < __private::max_value<S>()) { if (s > MAX_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(i16(static_cast<int16_t>(s))); } template <class S> requires((SignedPrimitiveEnum<S> || SignedPrimitiveEnumClass<S>) && ::sus::mem::size_of<S>() <= ::sus::mem::size_of<int16_t>()) __attribute__((pure)) static constexpr i16 from(S s) noexcept { using D = std::underlying_type_t<S>; return i16(static_cast<std::underlying_type_t<S>>(s)); } template <class S> requires(SignedPrimitiveEnum<S> || SignedPrimitiveEnumClass<S>) __attribute__((pure)) static constexpr ::sus::result::Result<i16, ::sus::num::TryFromIntError> try_from(S s) noexcept { using D = std::underlying_type_t<S>; using R = ::sus::result::Result<i16, ::sus::num::TryFromIntError>; if constexpr (MIN_PRIMITIVE > __private::min_value<D>()) { if (static_cast<D>(s) < MIN_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } if constexpr (MAX_PRIMITIVE < __private::max_value<D>()) { if (static_cast<D>(s) > MAX_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(i16(static_cast<int16_t>(s))); } template <UnsignedPrimitiveInteger U> __attribute__((pure)) static constexpr ::sus::result::Result<i16, ::sus::num::TryFromIntError> try_from(U u) noexcept { using R = ::sus::result::Result<i16, ::sus::num::TryFromIntError>; constexpr auto umax = __private::into_unsigned(MAX_PRIMITIVE); if constexpr (umax < __private::max_value<U>()) { if (u > umax) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(i16(static_cast<int16_t>(u))); } template <class U> requires(UnsignedPrimitiveEnum<U> || UnsignedPrimitiveEnumClass<U>) __attribute__((pure)) static constexpr ::sus::result::Result<i16, ::sus::num::TryFromIntError> try_from(U u) noexcept { using D = std::underlying_type_t<U>; using R = ::sus::result::Result<i16, ::sus::num::TryFromIntError>; constexpr auto umax = __private::into_unsigned(MAX_PRIMITIVE); if constexpr (umax < __private::max_value<D>()) { if (static_cast<D>(u) > umax) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(i16(static_cast<int16_t>(u))); } static constexpr i16 from_product( ::sus::iter::Iterator<i16> auto&& it) noexcept { auto p = i16(int16_t{1}); for (i16 i : ::sus::move(it)) p *= i; return p; } static constexpr i16 from_sum( ::sus::iter::Iterator<i16> auto&& it) noexcept { auto p = i16(int16_t{0}); for (i16 i : ::sus::move(it)) p += i; return p; } template <SignedPrimitiveInteger U> requires(::sus::mem::size_of<U>() >= ::sus::mem::size_of<int16_t>()) __attribute__((pure)) constexpr inline explicit operator U() const { return primitive_value; } __attribute__((pure)) constexpr bool is_negative() const& noexcept { return primitive_value < 0; } __attribute__((pure)) constexpr bool is_positive() const& noexcept { return primitive_value > 0; } __attribute__((pure)) constexpr i16 signum() const& noexcept { if (primitive_value < 0) return int16_t{-1}; else return int16_t{primitive_value != 0}; } [[nodiscard]] __attribute__((pure)) friend constexpr inline bool operator==( const i16& l, const i16& r) noexcept = default; template <SignedPrimitiveInteger P> [[nodiscard]] __attribute__((pure)) friend constexpr inline bool operator==( const i16& l, const P& r) noexcept { return l.primitive_value == r; } template <Signed S> [[nodiscard]] __attribute__((pure)) friend constexpr inline bool operator==( const i16& l, const S& r) noexcept { return l.primitive_value == r.primitive_value; } template <UnsignedPrimitiveInteger P> [[nodiscard]] __attribute__((pure)) friend constexpr inline std::strong_ordering operator<=>( const i16& l, const i16& r) noexcept { return l.primitive_value <=> r.primitive_value; } template <SignedPrimitiveInteger P> [[nodiscard]] __attribute__((pure)) friend constexpr inline std::strong_ordering operator<=>( const i16& l, const P& r) noexcept { return l.primitive_value <=> r; } template <Signed S> [[nodiscard]] __attribute__((pure)) friend constexpr inline std::strong_ordering operator<=>( const i16& l, const S& r) noexcept { return l.primitive_value <=> r.primitive_value; } __attribute__((pure)) constexpr inline i16 operator-() const& noexcept { ::sus::check(primitive_value != MIN_PRIMITIVE); return __private::unchecked_neg(primitive_value); } __attribute__((pure)) constexpr inline i16 operator~() const& noexcept { return __private::into_signed( __private::unchecked_not(__private::into_unsigned(primitive_value))); } [[nodiscard]] __attribute__((pure)) friend constexpr inline i16 operator+( const i16& l, const i16& r) noexcept { const auto out = __private::add_with_overflow(l.primitive_value, r.primitive_value); ::sus::check(!out.overflow); return out.value; } [[nodiscard]] __attribute__((pure)) friend constexpr inline i16 operator-( const i16& l, const i16& r) noexcept { const auto out = __private::sub_with_overflow(l.primitive_value, r.primitive_value); ::sus::check(!out.overflow); return out.value; } [[nodiscard]] __attribute__((pure)) friend constexpr inline i16 operator*( const i16& l, const i16& r) noexcept { const auto out = __private::mul_with_overflow(l.primitive_value, r.primitive_value); ::sus::check(!out.overflow); return out.value; } [[nodiscard]] __attribute__((pure)) friend constexpr inline i16 operator/( const i16& l, const i16& r) noexcept { ::sus::check(r.primitive_value != 0); ::sus::check(l.primitive_value != MIN_PRIMITIVE || r.primitive_value != -1); return static_cast<int16_t>(l.primitive_value / r.primitive_value); } [[nodiscard]] __attribute__((pure)) friend constexpr inline i16 operator%( const i16& l, const i16& r) noexcept { ::sus::check(r.primitive_value != 0); ::sus::check(l.primitive_value != MIN_PRIMITIVE || r.primitive_value != -1); return static_cast<int16_t>(l.primitive_value % r.primitive_value); } [[nodiscard]] __attribute__((pure)) friend constexpr inline i16 operator&( const i16& l, const i16& r) noexcept { return static_cast<int16_t>(l.primitive_value & r.primitive_value); } [[nodiscard]] __attribute__((pure)) friend constexpr inline i16 operator|( const i16& l, const i16& r) noexcept { return static_cast<int16_t>(l.primitive_value | r.primitive_value); } [[nodiscard]] __attribute__((pure)) friend constexpr inline i16 operator^( const i16& l, const i16& r) noexcept { return static_cast<int16_t>(l.primitive_value ^ r.primitive_value); } [[nodiscard]] __attribute__((pure)) friend constexpr inline i16 operator<<( const i16& l, const u32& r) noexcept { const auto out = __private::shl_with_overflow(l.primitive_value, r.primitive_value); ::sus::check(!out.overflow); return out.value; } [[nodiscard]] __attribute__((pure)) friend constexpr inline i16 operator>>( const i16& l, const u32& r) noexcept { const auto out = __private::shr_with_overflow(l.primitive_value, r.primitive_value); ::sus::check(!out.overflow); return out.value; } constexpr inline void operator+=(i16 r) & noexcept { const auto out = __private::add_with_overflow(primitive_value, r.primitive_value); ::sus::check(!out.overflow); primitive_value = out.value; } constexpr inline void operator-=(i16 r) & noexcept { const auto out = __private::sub_with_overflow(primitive_value, r.primitive_value); ::sus::check(!out.overflow); primitive_value = out.value; } constexpr inline void operator*=(i16 r) & noexcept { const auto out = __private::mul_with_overflow(primitive_value, r.primitive_value); ::sus::check(!out.overflow); primitive_value = out.value; } constexpr inline void operator/=(i16 r) & noexcept { ::sus::check(r.primitive_value != 0); ::sus::check(primitive_value != MIN_PRIMITIVE || r.primitive_value != -1); primitive_value /= r.primitive_value; } constexpr inline void operator%=(i16 r) & noexcept { ::sus::check(r.primitive_value != 0); ::sus::check(primitive_value != MIN_PRIMITIVE || r.primitive_value != -1); primitive_value %= r.primitive_value; } constexpr inline void operator&=(i16 r) & noexcept { primitive_value &= r.primitive_value; } constexpr inline void operator|=(i16 r) & noexcept { primitive_value |= r.primitive_value; } constexpr inline void operator^=(i16 r) & noexcept { primitive_value ^= r.primitive_value; } constexpr inline void operator<<=(const u32& r) & noexcept { const auto out = __private::shl_with_overflow(primitive_value, r.primitive_value); ::sus::check(!out.overflow); primitive_value = out.value; } constexpr inline void operator>>=(const u32& r) & noexcept { const auto out = __private::shr_with_overflow(primitive_value, r.primitive_value); ::sus::check(!out.overflow); primitive_value = out.value; } __attribute__((pure)) constexpr inline i16 abs() const& noexcept { ::sus::check(primitive_value != MIN_PRIMITIVE); if (primitive_value >= 0) return primitive_value; else return __private::unchecked_neg(primitive_value); } __attribute__((pure)) constexpr Option<i16> checked_abs() const& noexcept { if (primitive_value != MIN_PRIMITIVE) [[likely]] return Option<i16>::with(abs()); else return Option<i16>(); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i16, bool>> __attribute__((pure)) constexpr Tuple overflowing_abs() const& noexcept { if (primitive_value != MIN_PRIMITIVE) [[likely]] return Tuple::with(abs(), false); else return Tuple::with(MIN, true); } __attribute__((pure)) constexpr i16 saturating_abs() const& noexcept { if (primitive_value != MIN_PRIMITIVE) [[likely]] return abs(); else return MAX; } __attribute__((pure)) constexpr u16 unsigned_abs() const& noexcept { if (primitive_value >= 0) { return __private::into_unsigned(primitive_value); } else { const auto neg_plus_one = __private::unchecked_add(primitive_value, int16_t{1}); const auto pos_minus_one = __private::into_unsigned(__private::unchecked_neg(neg_plus_one)); return __private::unchecked_add(pos_minus_one, decltype(pos_minus_one){1}); } } __attribute__((pure)) constexpr i16 wrapping_abs() const& noexcept { if (primitive_value != MIN_PRIMITIVE) [[likely]] return abs(); else return MIN; } __attribute__((pure)) constexpr u16 abs_diff(const i16& r) const& noexcept { if (primitive_value >= r.primitive_value) { return __private::sub_with_unsigned_positive_result(primitive_value, r.primitive_value); } else { return __private::sub_with_unsigned_positive_result(r.primitive_value, primitive_value); } } __attribute__((pure)) constexpr Option<i16> checked_add(const i16& rhs) const& noexcept { const auto out = __private::add_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return Option<i16>::with(out.value); else return Option<i16>(); } __attribute__((pure)) constexpr Option<i16> checked_add_unsigned( const u16& rhs) const& noexcept { const auto out = __private::add_with_overflow_unsigned(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return Option<i16>::with(out.value); else return Option<i16>(); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i16, bool>> __attribute__((pure)) constexpr Tuple overflowing_add(const i16& rhs) const& noexcept { const auto r = __private::add_with_overflow(primitive_value, rhs.primitive_value); return Tuple::with(r.value, r.overflow); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i16, bool>> __attribute__((pure)) constexpr Tuple overflowing_add_unsigned( const u16& rhs) const& noexcept { const auto r = __private::add_with_overflow_unsigned(primitive_value, rhs.primitive_value); return Tuple::with(r.value, r.overflow); } __attribute__((pure)) constexpr i16 saturating_add(const i16& rhs) const& noexcept { return __private::saturating_add(primitive_value, rhs.primitive_value); } __attribute__((pure)) constexpr i16 saturating_add_unsigned( const u16& rhs) const& noexcept { const auto r = __private::add_with_overflow_unsigned(primitive_value, rhs.primitive_value); if (!r.overflow) [[likely]] return r.value; else return MAX; } __attribute__((pure)) inline constexpr i16 unchecked_add( ::sus::marker::UnsafeFnMarker, const i16& rhs) const& noexcept { return __private::unchecked_add(primitive_value, rhs.primitive_value); } __attribute__((pure)) constexpr i16 wrapping_add(const i16& rhs) const& noexcept { return __private::wrapping_add(primitive_value, rhs.primitive_value); } __attribute__((pure)) constexpr i16 wrapping_add_unsigned( const u16& rhs) const& noexcept { return __private::add_with_overflow_unsigned(primitive_value, rhs.primitive_value) .value; } __attribute__((pure)) constexpr Option<i16> checked_div(const i16& rhs) const& noexcept { if (__private::div_overflows(primitive_value, rhs.primitive_value)) [[unlikely]] return Option<i16>(); else return Option<i16>::with( __private::unchecked_div(primitive_value, rhs.primitive_value)); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i16, bool>> __attribute__((pure)) constexpr Tuple overflowing_div(const i16& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0); if (__private::div_overflows_nonzero(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)) [[unlikely]] { return Tuple::with(MIN, true); } else { return Tuple::with( __private::unchecked_div(primitive_value, rhs.primitive_value), false); } } __attribute__((pure)) constexpr i16 saturating_div(const i16& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0); if (__private::div_overflows_nonzero(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)) [[unlikely]] { return MAX; } else { return __private::unchecked_div(primitive_value, rhs.primitive_value); } } __attribute__((pure)) constexpr i16 wrapping_div(const i16& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0); if (__private::div_overflows_nonzero(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)) [[unlikely]] { return MIN; } else { return __private::unchecked_div(primitive_value, rhs.primitive_value); } } __attribute__((pure)) constexpr Option<i16> checked_mul(const i16& rhs) const& noexcept { const auto out = __private::mul_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return Option<i16>::with(out.value); else return Option<i16>(); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i16, bool>> __attribute__((pure)) constexpr Tuple overflowing_mul(const i16& rhs) const& noexcept { const auto out = __private::mul_with_overflow(primitive_value, rhs.primitive_value); return Tuple::with(out.value, out.overflow); } __attribute__((pure)) constexpr i16 saturating_mul(const i16& rhs) const& noexcept { return __private::saturating_mul(primitive_value, rhs.primitive_value); } __attribute__((pure)) constexpr inline i16 unchecked_mul( ::sus::marker::UnsafeFnMarker, const i16& rhs) const& noexcept { return __private::unchecked_mul(primitive_value, rhs.primitive_value); } __attribute__((pure)) constexpr i16 wrapping_mul(const i16& rhs) const& noexcept { return __private::wrapping_mul(primitive_value, rhs.primitive_value); } __attribute__((pure)) constexpr Option<i16> checked_neg() const& noexcept { if (primitive_value != MIN_PRIMITIVE) [[likely]] return Option<i16>::with(__private::unchecked_neg(primitive_value)); else return Option<i16>(); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i16, bool>> __attribute__((pure)) constexpr Tuple overflowing_neg() const& noexcept { if (primitive_value != MIN_PRIMITIVE) [[likely]] return Tuple::with(__private::unchecked_neg(primitive_value), false); else return Tuple::with(MIN, true); } __attribute__((pure)) constexpr i16 saturating_neg() const& noexcept { if (primitive_value != MIN_PRIMITIVE) [[likely]] return __private::unchecked_neg(primitive_value); else return MAX; } __attribute__((pure)) constexpr i16 wrapping_neg() const& noexcept { if (primitive_value != MIN_PRIMITIVE) [[likely]] return __private::unchecked_neg(primitive_value); else return MIN; } __attribute__((pure)) constexpr Option<i16> checked_rem(const i16& rhs) const& noexcept { if (__private::div_overflows(primitive_value, rhs.primitive_value)) [[unlikely]] return Option<i16>(); else return Option<i16>::with( static_cast<int16_t>(primitive_value % rhs.primitive_value)); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i16, bool>> __attribute__((pure)) constexpr Tuple overflowing_rem(const i16& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0); if (__private::div_overflows_nonzero(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)) [[unlikely]] { return Tuple::with(int16_t{0}, true); } else { return Tuple::with( static_cast<int16_t>(primitive_value % rhs.primitive_value), false); } } __attribute__((pure)) constexpr i16 wrapping_rem(const i16& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0); if (__private::div_overflows_nonzero(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)) [[likely]] { return int16_t{0}; } else { return static_cast<int16_t>(primitive_value % rhs.primitive_value); } } __attribute__((pure)) constexpr i16 div_euclid(const i16& rhs) const& noexcept { ::sus::check(!__private::div_overflows(primitive_value, rhs.primitive_value)); return __private::div_euclid(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value); } __attribute__((pure)) constexpr Option<i16> checked_div_euclid( const i16& rhs) const& noexcept { if (__private::div_overflows(primitive_value, rhs.primitive_value)) [[unlikely]] { return Option<i16>(); } else { return Option<i16>::with(__private::div_euclid( ::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)); } } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i16, bool>> __attribute__((pure)) constexpr Tuple overflowing_div_euclid( const i16& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0); if (__private::div_overflows_nonzero(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)) [[unlikely]] { return Tuple::with(MIN, true); } else { return Tuple::with( __private::div_euclid(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value), false); } } __attribute__((pure)) constexpr i16 wrapping_div_euclid(const i16& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0); if (__private::div_overflows_nonzero(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)) [[unlikely]] { return MIN; } else { return __private::div_euclid(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value); } } __attribute__((pure)) constexpr i16 rem_euclid(const i16& rhs) const& noexcept { ::sus::check(!__private::div_overflows(primitive_value, rhs.primitive_value)); return __private::rem_euclid(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value); } __attribute__((pure)) constexpr Option<i16> checked_rem_euclid( const i16& rhs) const& noexcept { if (__private::div_overflows(primitive_value, rhs.primitive_value)) [[unlikely]] { return Option<i16>(); } else { return Option<i16>::with(__private::rem_euclid( ::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)); } } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i16, bool>> __attribute__((pure)) constexpr Tuple overflowing_rem_euclid( const i16& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0); if (__private::div_overflows_nonzero(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)) [[unlikely]] { return Tuple::with(int16_t{0}, true); } else { return Tuple::with( __private::rem_euclid(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value), false); } } __attribute__((pure)) constexpr i16 wrapping_rem_euclid(const i16& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0); if (__private::div_overflows_nonzero(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)) [[unlikely]] { return int16_t{0}; } else { return __private::rem_euclid(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value); } } __attribute__((pure)) constexpr Option<i16> checked_shl(const u32& rhs) const& noexcept { const auto out = __private::shl_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return Option<i16>::with(out.value); else return Option<i16>(); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i16, bool>> __attribute__((pure)) constexpr Tuple overflowing_shl(const u32& rhs) const& noexcept { const auto out = __private::shl_with_overflow(primitive_value, rhs.primitive_value); return Tuple::with(out.value, out.overflow); } __attribute__((pure)) constexpr i16 wrapping_shl(const u32& rhs) const& noexcept { return __private::shl_with_overflow(primitive_value, rhs.primitive_value) .value; } __attribute__((pure)) constexpr Option<i16> checked_shr(const u32& rhs) const& noexcept { const auto out = __private::shr_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return Option<i16>::with(out.value); else return Option<i16>(); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i16, bool>> __attribute__((pure)) constexpr Tuple overflowing_shr(const u32& rhs) const& noexcept { const auto out = __private::shr_with_overflow(primitive_value, rhs.primitive_value); return Tuple::with(out.value, out.overflow); } __attribute__((pure)) constexpr i16 wrapping_shr(const u32& rhs) const& noexcept { return __private::shr_with_overflow(primitive_value, rhs.primitive_value) .value; } __attribute__((pure)) constexpr Option<i16> checked_sub(const i16& rhs) const& { const auto out = __private::sub_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return Option<i16>::with(out.value); else return Option<i16>(); } __attribute__((pure)) constexpr Option<i16> checked_sub_unsigned( const u16& rhs) const& { const auto out = __private::sub_with_overflow_unsigned(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return Option<i16>::with(out.value); else return Option<i16>(); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i16, bool>> __attribute__((pure)) constexpr Tuple overflowing_sub(const i16& rhs) const& noexcept { const auto out = __private::sub_with_overflow(primitive_value, rhs.primitive_value); return Tuple::with(out.value, out.overflow); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i16, bool>> __attribute__((pure)) constexpr Tuple overflowing_sub_unsigned( const u16& rhs) const& noexcept { const auto out = __private::sub_with_overflow_unsigned(primitive_value, rhs.primitive_value); return Tuple::with(out.value, out.overflow); } __attribute__((pure)) constexpr i16 saturating_sub(const i16& rhs) const& { return __private::saturating_sub(primitive_value, rhs.primitive_value); } __attribute__((pure)) constexpr i16 saturating_sub_unsigned(const u16& rhs) const& { const auto out = __private::sub_with_overflow_unsigned(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return out.value; else return MIN; } __attribute__((pure)) inline constexpr i16 unchecked_sub(::sus::marker::UnsafeFnMarker, const i16& rhs) const& { return static_cast<int16_t>(primitive_value - rhs.primitive_value); } constexpr i16 wrapping_sub(const i16& rhs) const& { return __private::wrapping_sub(primitive_value, rhs.primitive_value); } __attribute__((pure)) constexpr i16 wrapping_sub_unsigned(const u16& rhs) const& { return __private::sub_with_overflow_unsigned(primitive_value, rhs.primitive_value) .value; } __attribute__((pure)) constexpr u32 count_ones() const& noexcept { return __private::count_ones(__private::into_unsigned(primitive_value)); } __attribute__((pure)) constexpr u32 count_zeros() const& noexcept { return (~(*this)).count_ones(); } __attribute__((pure)) constexpr u32 leading_ones() const& noexcept { return (~(*this)).leading_zeros(); } __attribute__((pure)) constexpr u32 leading_zeros() const& noexcept { return __private::leading_zeros(__private::into_unsigned(primitive_value)); } __attribute__((pure)) constexpr u32 trailing_ones() const& noexcept { return (~(*this)).trailing_zeros(); } __attribute__((pure)) constexpr u32 trailing_zeros() const& noexcept { return __private::trailing_zeros(__private::into_unsigned(primitive_value)); } __attribute__((pure)) constexpr i16 reverse_bits() const& noexcept { return __private::into_signed( __private::reverse_bits(__private::into_unsigned(primitive_value))); } __attribute__((pure)) constexpr i16 rotate_left(const u32& n) const& noexcept { return __private::into_signed(__private::rotate_left( __private::into_unsigned(primitive_value), n.primitive_value)); } __attribute__((pure)) constexpr i16 rotate_right(const u32& n) const& noexcept { return __private::into_signed(__private::rotate_right( __private::into_unsigned(primitive_value), n.primitive_value)); } __attribute__((pure)) constexpr i16 swap_bytes() const& noexcept { return __private::into_signed( __private::swap_bytes(__private::into_unsigned(primitive_value))); } __attribute__((pure)) constexpr inline i16 pow(const u32& rhs) const& noexcept { const auto out = __private::pow_with_overflow(primitive_value, rhs.primitive_value); ::sus::check(!out.overflow); return out.value; } __attribute__((pure)) constexpr Option<i16> checked_pow(const u32& rhs) const& noexcept { const auto out = __private::pow_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return Option<i16>::with(out.value); else return Option<i16>(); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i16, bool>> __attribute__((pure)) constexpr Tuple overflowing_pow(const u32& exp) const& noexcept { const auto out = __private::pow_with_overflow(primitive_value, exp.primitive_value); return Tuple::with(out.value, out.overflow); } __attribute__((pure)) constexpr i16 wrapping_pow(const u32& exp) const& noexcept { return __private::wrapping_pow(primitive_value, exp.primitive_value); } __attribute__((pure)) constexpr Option<u32> checked_log2() const& { if (primitive_value <= 0) [[unlikely]] { return Option<u32>(); } else { uint32_t zeros = __private::leading_zeros_nonzero( ::sus::marker::unsafe_fn, __private::into_unsigned(primitive_value)); return Option<u32>::with(BITS - 1_u32 - u32(zeros)); } } __attribute__((pure)) constexpr u32 log2() const& { return checked_log2().unwrap(); } __attribute__((pure)) constexpr Option<u32> checked_log10() const& { if (primitive_value <= 0) [[unlikely]] { return Option<u32>(); } else { return Option<u32>::with(__private::int_log10::i16(primitive_value)); } } __attribute__((pure)) constexpr u32 log10() const& { return checked_log10().unwrap(); } __attribute__((pure)) constexpr Option<u32> checked_log(const i16& base) const& noexcept { if (primitive_value <= 0 || base.primitive_value <= 1) [[unlikely]] { return Option<u32>(); } else { auto n = uint32_t{0}; auto r = primitive_value; const auto b = base.primitive_value; while (r >= b) { r /= b; n += 1u; } return Option<u32>::with(n); } } __attribute__((pure)) constexpr u32 log(const i16& base) const& noexcept { return checked_log(base).unwrap(); } __attribute__((pure)) static constexpr i16 from_be(const i16& x) noexcept { if constexpr (::sus::assertions::is_big_endian()) return x; else return x.swap_bytes(); } __attribute__((pure)) static constexpr i16 from_le(const i16& x) noexcept { if constexpr (::sus::assertions::is_little_endian()) return x; else return x.swap_bytes(); } __attribute__((pure)) constexpr i16 to_be() const& noexcept { if constexpr (::sus::assertions::is_big_endian()) return *this; else return swap_bytes(); } __attribute__((pure)) constexpr i16 to_le() const& noexcept { if constexpr (::sus::assertions::is_little_endian()) return *this; else return swap_bytes(); } __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<int16_t>()> to_be_bytes() const& noexcept; __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<int16_t>()> to_le_bytes() const& noexcept; __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<int16_t>()> to_ne_bytes() const& noexcept; __attribute__((pure)) static constexpr i16 from_be_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<int16_t>()>& bytes) noexcept; __attribute__((pure)) static constexpr i16 from_le_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<int16_t>()>& bytes) noexcept; __attribute__((pure)) static constexpr i16 from_ne_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<int16_t>()>& bytes) noexcept; }; inline constexpr i16 i16::MIN = i16(i16::MIN_PRIMITIVE); inline constexpr i16 i16::MAX = i16(i16::MAX_PRIMITIVE); inline constexpr u32 i16::BITS = u32(__private::num_bits<int16_t>()); struct i64 final { int64_t primitive_value{0}; static constexpr auto MIN_PRIMITIVE = __private::min_value<int64_t>(); static constexpr auto MAX_PRIMITIVE = __private::max_value<int64_t>(); static const i64 MIN; static const i64 MAX; static const u32 BITS; constexpr inline i64() noexcept = default; template <Signed S> requires(::sus::mem::size_of<S>() <= ::sus::mem::size_of<int64_t>()) constexpr inline i64(S v) noexcept : primitive_value(v.primitive_value) {} template <SignedPrimitiveInteger P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of<int64_t>()) constexpr inline i64(P v) noexcept : primitive_value(v) {} template <SignedPrimitiveEnum P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of<int64_t>()) constexpr inline i64(P v) noexcept : primitive_value(v) {} template <SignedPrimitiveEnumClass P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of<int64_t>()) explicit constexpr inline i64(P v) noexcept : primitive_value(static_cast<int64_t>(v)) {} template <Unsigned U> requires(::sus::mem::size_of<U>() < ::sus::mem::size_of<int64_t>()) constexpr inline i64(U v) noexcept : primitive_value(v.primitive_value) {} template <UnsignedPrimitiveInteger P> requires(::sus::mem::size_of<P>() < ::sus::mem::size_of<int64_t>()) constexpr inline i64(P v) noexcept : primitive_value(v) {} template <UnsignedPrimitiveEnum P> requires(::sus::mem::size_of<P>() < ::sus::mem::size_of<int64_t>()) constexpr inline i64(P v) noexcept : primitive_value(v) {} template <UnsignedPrimitiveEnumClass P> requires(::sus::mem::size_of<P>() < ::sus::mem::size_of<int64_t>()) explicit constexpr inline i64(P v) noexcept : primitive_value(static_cast<int64_t>(v)) {} template <Signed S> requires(::sus::mem::size_of<S>() <= ::sus::mem::size_of<int64_t>()) constexpr inline i64& operator=(S v) noexcept { primitive_value = v.primitive_value; return *this; } template <SignedPrimitiveInteger P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of<int64_t>()) constexpr inline i64& operator=(P v) noexcept { primitive_value = v; return *this; } template <SignedPrimitiveEnum P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of<int64_t>()) constexpr inline i64& operator=(P v) noexcept { primitive_value = v; return *this; } template <Signed S> requires(::sus::mem::size_of<S>() <= ::sus::mem::size_of<int64_t>()) __attribute__((pure)) static constexpr i64 from(S s) noexcept { return i64(s); } template <Signed S> __attribute__((pure)) static constexpr ::sus::result::Result<i64, ::sus::num::TryFromIntError> try_from(S s) noexcept { using R = ::sus::result::Result<i64, ::sus::num::TryFromIntError>; if constexpr (MIN_PRIMITIVE > S::MIN_PRIMITIVE) { if (s.primitive_value < MIN_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } if constexpr (MAX_PRIMITIVE < S::MAX_PRIMITIVE) { if (s.primitive_value > MAX_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(i64(static_cast<int64_t>(s.primitive_value))); } template <Unsigned U> __attribute__((pure)) static constexpr ::sus::result::Result<i64, ::sus::num::TryFromIntError> try_from(U u) noexcept { using R = ::sus::result::Result<i64, ::sus::num::TryFromIntError>; constexpr auto umax = __private::into_unsigned(MAX_PRIMITIVE); if constexpr (umax < U::MAX_PRIMITIVE) { if (u.primitive_value > umax) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(i64(static_cast<int64_t>(u.primitive_value))); } template <SignedPrimitiveInteger S> requires(::sus::mem::size_of<S>() <= ::sus::mem::size_of<int64_t>()) __attribute__((pure)) static constexpr i64 from(S s) noexcept { return i64(s); } template <SignedPrimitiveInteger S> __attribute__((pure)) static constexpr ::sus::result::Result<i64, ::sus::num::TryFromIntError> try_from(S s) noexcept { using R = ::sus::result::Result<i64, ::sus::num::TryFromIntError>; if constexpr (MIN_PRIMITIVE > __private::min_value<S>()) { if (s < MIN_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } if constexpr (MAX_PRIMITIVE < __private::max_value<S>()) { if (s > MAX_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(i64(static_cast<int64_t>(s))); } template <class S> requires((SignedPrimitiveEnum<S> || SignedPrimitiveEnumClass<S>) && ::sus::mem::size_of<S>() <= ::sus::mem::size_of<int64_t>()) __attribute__((pure)) static constexpr i64 from(S s) noexcept { using D = std::underlying_type_t<S>; return i64(static_cast<std::underlying_type_t<S>>(s)); } template <class S> requires(SignedPrimitiveEnum<S> || SignedPrimitiveEnumClass<S>) __attribute__((pure)) static constexpr ::sus::result::Result<i64, ::sus::num::TryFromIntError> try_from(S s) noexcept { using D = std::underlying_type_t<S>; using R = ::sus::result::Result<i64, ::sus::num::TryFromIntError>; if constexpr (MIN_PRIMITIVE > __private::min_value<D>()) { if (static_cast<D>(s) < MIN_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } if constexpr (MAX_PRIMITIVE < __private::max_value<D>()) { if (static_cast<D>(s) > MAX_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(i64(static_cast<int64_t>(s))); } template <UnsignedPrimitiveInteger U> __attribute__((pure)) static constexpr ::sus::result::Result<i64, ::sus::num::TryFromIntError> try_from(U u) noexcept { using R = ::sus::result::Result<i64, ::sus::num::TryFromIntError>; constexpr auto umax = __private::into_unsigned(MAX_PRIMITIVE); if constexpr (umax < __private::max_value<U>()) { if (u > umax) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(i64(static_cast<int64_t>(u))); } template <class U> requires(UnsignedPrimitiveEnum<U> || UnsignedPrimitiveEnumClass<U>) __attribute__((pure)) static constexpr ::sus::result::Result<i64, ::sus::num::TryFromIntError> try_from(U u) noexcept { using D = std::underlying_type_t<U>; using R = ::sus::result::Result<i64, ::sus::num::TryFromIntError>; constexpr auto umax = __private::into_unsigned(MAX_PRIMITIVE); if constexpr (umax < __private::max_value<D>()) { if (static_cast<D>(u) > umax) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(i64(static_cast<int64_t>(u))); } static constexpr i64 from_product( ::sus::iter::Iterator<i64> auto&& it) noexcept { auto p = i64(int64_t{1}); for (i64 i : ::sus::move(it)) p *= i; return p; } static constexpr i64 from_sum( ::sus::iter::Iterator<i64> auto&& it) noexcept { auto p = i64(int64_t{0}); for (i64 i : ::sus::move(it)) p += i; return p; } template <SignedPrimitiveInteger U> requires(::sus::mem::size_of<U>() >= ::sus::mem::size_of<int64_t>()) __attribute__((pure)) constexpr inline explicit operator U() const { return primitive_value; } __attribute__((pure)) constexpr bool is_negative() const& noexcept { return primitive_value < 0; } __attribute__((pure)) constexpr bool is_positive() const& noexcept { return primitive_value > 0; } __attribute__((pure)) constexpr i64 signum() const& noexcept { if (primitive_value < 0) return int64_t{-1}; else return int64_t{primitive_value != 0}; } [[nodiscard]] __attribute__((pure)) friend constexpr inline bool operator==( const i64& l, const i64& r) noexcept = default; template <SignedPrimitiveInteger P> [[nodiscard]] __attribute__((pure)) friend constexpr inline bool operator==( const i64& l, const P& r) noexcept { return l.primitive_value == r; } template <Signed S> [[nodiscard]] __attribute__((pure)) friend constexpr inline bool operator==( const i64& l, const S& r) noexcept { return l.primitive_value == r.primitive_value; } template <UnsignedPrimitiveInteger P> [[nodiscard]] __attribute__((pure)) friend constexpr inline std::strong_ordering operator<=>( const i64& l, const i64& r) noexcept { return l.primitive_value <=> r.primitive_value; } template <SignedPrimitiveInteger P> [[nodiscard]] __attribute__((pure)) friend constexpr inline std::strong_ordering operator<=>( const i64& l, const P& r) noexcept { return l.primitive_value <=> r; } template <Signed S> [[nodiscard]] __attribute__((pure)) friend constexpr inline std::strong_ordering operator<=>( const i64& l, const S& r) noexcept { return l.primitive_value <=> r.primitive_value; } __attribute__((pure)) constexpr inline i64 operator-() const& noexcept { ::sus::check(primitive_value != MIN_PRIMITIVE); return __private::unchecked_neg(primitive_value); } __attribute__((pure)) constexpr inline i64 operator~() const& noexcept { return __private::into_signed( __private::unchecked_not(__private::into_unsigned(primitive_value))); } [[nodiscard]] __attribute__((pure)) friend constexpr inline i64 operator+( const i64& l, const i64& r) noexcept { const auto out = __private::add_with_overflow(l.primitive_value, r.primitive_value); ::sus::check(!out.overflow); return out.value; } [[nodiscard]] __attribute__((pure)) friend constexpr inline i64 operator-( const i64& l, const i64& r) noexcept { const auto out = __private::sub_with_overflow(l.primitive_value, r.primitive_value); ::sus::check(!out.overflow); return out.value; } [[nodiscard]] __attribute__((pure)) friend constexpr inline i64 operator*( const i64& l, const i64& r) noexcept { const auto out = __private::mul_with_overflow(l.primitive_value, r.primitive_value); ::sus::check(!out.overflow); return out.value; } [[nodiscard]] __attribute__((pure)) friend constexpr inline i64 operator/( const i64& l, const i64& r) noexcept { ::sus::check(r.primitive_value != 0); ::sus::check(l.primitive_value != MIN_PRIMITIVE || r.primitive_value != -1); return static_cast<int64_t>(l.primitive_value / r.primitive_value); } [[nodiscard]] __attribute__((pure)) friend constexpr inline i64 operator%( const i64& l, const i64& r) noexcept { ::sus::check(r.primitive_value != 0); ::sus::check(l.primitive_value != MIN_PRIMITIVE || r.primitive_value != -1); return static_cast<int64_t>(l.primitive_value % r.primitive_value); } [[nodiscard]] __attribute__((pure)) friend constexpr inline i64 operator&( const i64& l, const i64& r) noexcept { return static_cast<int64_t>(l.primitive_value & r.primitive_value); } [[nodiscard]] __attribute__((pure)) friend constexpr inline i64 operator|( const i64& l, const i64& r) noexcept { return static_cast<int64_t>(l.primitive_value | r.primitive_value); } [[nodiscard]] __attribute__((pure)) friend constexpr inline i64 operator^( const i64& l, const i64& r) noexcept { return static_cast<int64_t>(l.primitive_value ^ r.primitive_value); } [[nodiscard]] __attribute__((pure)) friend constexpr inline i64 operator<<( const i64& l, const u32& r) noexcept { const auto out = __private::shl_with_overflow(l.primitive_value, r.primitive_value); ::sus::check(!out.overflow); return out.value; } [[nodiscard]] __attribute__((pure)) friend constexpr inline i64 operator>>( const i64& l, const u32& r) noexcept { const auto out = __private::shr_with_overflow(l.primitive_value, r.primitive_value); ::sus::check(!out.overflow); return out.value; } constexpr inline void operator+=(i64 r) & noexcept { const auto out = __private::add_with_overflow(primitive_value, r.primitive_value); ::sus::check(!out.overflow); primitive_value = out.value; } constexpr inline void operator-=(i64 r) & noexcept { const auto out = __private::sub_with_overflow(primitive_value, r.primitive_value); ::sus::check(!out.overflow); primitive_value = out.value; } constexpr inline void operator*=(i64 r) & noexcept { const auto out = __private::mul_with_overflow(primitive_value, r.primitive_value); ::sus::check(!out.overflow); primitive_value = out.value; } constexpr inline void operator/=(i64 r) & noexcept { ::sus::check(r.primitive_value != 0); ::sus::check(primitive_value != MIN_PRIMITIVE || r.primitive_value != -1); primitive_value /= r.primitive_value; } constexpr inline void operator%=(i64 r) & noexcept { ::sus::check(r.primitive_value != 0); ::sus::check(primitive_value != MIN_PRIMITIVE || r.primitive_value != -1); primitive_value %= r.primitive_value; } constexpr inline void operator&=(i64 r) & noexcept { primitive_value &= r.primitive_value; } constexpr inline void operator|=(i64 r) & noexcept { primitive_value |= r.primitive_value; } constexpr inline void operator^=(i64 r) & noexcept { primitive_value ^= r.primitive_value; } constexpr inline void operator<<=(const u32& r) & noexcept { const auto out = __private::shl_with_overflow(primitive_value, r.primitive_value); ::sus::check(!out.overflow); primitive_value = out.value; } constexpr inline void operator>>=(const u32& r) & noexcept { const auto out = __private::shr_with_overflow(primitive_value, r.primitive_value); ::sus::check(!out.overflow); primitive_value = out.value; } __attribute__((pure)) constexpr inline i64 abs() const& noexcept { ::sus::check(primitive_value != MIN_PRIMITIVE); if (primitive_value >= 0) return primitive_value; else return __private::unchecked_neg(primitive_value); } __attribute__((pure)) constexpr Option<i64> checked_abs() const& noexcept { if (primitive_value != MIN_PRIMITIVE) [[likely]] return Option<i64>::with(abs()); else return Option<i64>(); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i64, bool>> __attribute__((pure)) constexpr Tuple overflowing_abs() const& noexcept { if (primitive_value != MIN_PRIMITIVE) [[likely]] return Tuple::with(abs(), false); else return Tuple::with(MIN, true); } __attribute__((pure)) constexpr i64 saturating_abs() const& noexcept { if (primitive_value != MIN_PRIMITIVE) [[likely]] return abs(); else return MAX; } __attribute__((pure)) constexpr u64 unsigned_abs() const& noexcept { if (primitive_value >= 0) { return __private::into_unsigned(primitive_value); } else { const auto neg_plus_one = __private::unchecked_add(primitive_value, int64_t{1}); const auto pos_minus_one = __private::into_unsigned(__private::unchecked_neg(neg_plus_one)); return __private::unchecked_add(pos_minus_one, decltype(pos_minus_one){1}); } } __attribute__((pure)) constexpr i64 wrapping_abs() const& noexcept { if (primitive_value != MIN_PRIMITIVE) [[likely]] return abs(); else return MIN; } __attribute__((pure)) constexpr u64 abs_diff(const i64& r) const& noexcept { if (primitive_value >= r.primitive_value) { return __private::sub_with_unsigned_positive_result(primitive_value, r.primitive_value); } else { return __private::sub_with_unsigned_positive_result(r.primitive_value, primitive_value); } } __attribute__((pure)) constexpr Option<i64> checked_add(const i64& rhs) const& noexcept { const auto out = __private::add_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return Option<i64>::with(out.value); else return Option<i64>(); } __attribute__((pure)) constexpr Option<i64> checked_add_unsigned( const u64& rhs) const& noexcept { const auto out = __private::add_with_overflow_unsigned(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return Option<i64>::with(out.value); else return Option<i64>(); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i64, bool>> __attribute__((pure)) constexpr Tuple overflowing_add(const i64& rhs) const& noexcept { const auto r = __private::add_with_overflow(primitive_value, rhs.primitive_value); return Tuple::with(r.value, r.overflow); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i64, bool>> __attribute__((pure)) constexpr Tuple overflowing_add_unsigned( const u64& rhs) const& noexcept { const auto r = __private::add_with_overflow_unsigned(primitive_value, rhs.primitive_value); return Tuple::with(r.value, r.overflow); } __attribute__((pure)) constexpr i64 saturating_add(const i64& rhs) const& noexcept { return __private::saturating_add(primitive_value, rhs.primitive_value); } __attribute__((pure)) constexpr i64 saturating_add_unsigned( const u64& rhs) const& noexcept { const auto r = __private::add_with_overflow_unsigned(primitive_value, rhs.primitive_value); if (!r.overflow) [[likely]] return r.value; else return MAX; } __attribute__((pure)) inline constexpr i64 unchecked_add( ::sus::marker::UnsafeFnMarker, const i64& rhs) const& noexcept { return __private::unchecked_add(primitive_value, rhs.primitive_value); } __attribute__((pure)) constexpr i64 wrapping_add(const i64& rhs) const& noexcept { return __private::wrapping_add(primitive_value, rhs.primitive_value); } __attribute__((pure)) constexpr i64 wrapping_add_unsigned( const u64& rhs) const& noexcept { return __private::add_with_overflow_unsigned(primitive_value, rhs.primitive_value) .value; } __attribute__((pure)) constexpr Option<i64> checked_div(const i64& rhs) const& noexcept { if (__private::div_overflows(primitive_value, rhs.primitive_value)) [[unlikely]] return Option<i64>(); else return Option<i64>::with( __private::unchecked_div(primitive_value, rhs.primitive_value)); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i64, bool>> __attribute__((pure)) constexpr Tuple overflowing_div(const i64& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0); if (__private::div_overflows_nonzero(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)) [[unlikely]] { return Tuple::with(MIN, true); } else { return Tuple::with( __private::unchecked_div(primitive_value, rhs.primitive_value), false); } } __attribute__((pure)) constexpr i64 saturating_div(const i64& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0); if (__private::div_overflows_nonzero(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)) [[unlikely]] { return MAX; } else { return __private::unchecked_div(primitive_value, rhs.primitive_value); } } __attribute__((pure)) constexpr i64 wrapping_div(const i64& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0); if (__private::div_overflows_nonzero(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)) [[unlikely]] { return MIN; } else { return __private::unchecked_div(primitive_value, rhs.primitive_value); } } __attribute__((pure)) constexpr Option<i64> checked_mul(const i64& rhs) const& noexcept { const auto out = __private::mul_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return Option<i64>::with(out.value); else return Option<i64>(); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i64, bool>> __attribute__((pure)) constexpr Tuple overflowing_mul(const i64& rhs) const& noexcept { const auto out = __private::mul_with_overflow(primitive_value, rhs.primitive_value); return Tuple::with(out.value, out.overflow); } __attribute__((pure)) constexpr i64 saturating_mul(const i64& rhs) const& noexcept { return __private::saturating_mul(primitive_value, rhs.primitive_value); } __attribute__((pure)) constexpr inline i64 unchecked_mul( ::sus::marker::UnsafeFnMarker, const i64& rhs) const& noexcept { return __private::unchecked_mul(primitive_value, rhs.primitive_value); } __attribute__((pure)) constexpr i64 wrapping_mul(const i64& rhs) const& noexcept { return __private::wrapping_mul(primitive_value, rhs.primitive_value); } __attribute__((pure)) constexpr Option<i64> checked_neg() const& noexcept { if (primitive_value != MIN_PRIMITIVE) [[likely]] return Option<i64>::with(__private::unchecked_neg(primitive_value)); else return Option<i64>(); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i64, bool>> __attribute__((pure)) constexpr Tuple overflowing_neg() const& noexcept { if (primitive_value != MIN_PRIMITIVE) [[likely]] return Tuple::with(__private::unchecked_neg(primitive_value), false); else return Tuple::with(MIN, true); } __attribute__((pure)) constexpr i64 saturating_neg() const& noexcept { if (primitive_value != MIN_PRIMITIVE) [[likely]] return __private::unchecked_neg(primitive_value); else return MAX; } __attribute__((pure)) constexpr i64 wrapping_neg() const& noexcept { if (primitive_value != MIN_PRIMITIVE) [[likely]] return __private::unchecked_neg(primitive_value); else return MIN; } __attribute__((pure)) constexpr Option<i64> checked_rem(const i64& rhs) const& noexcept { if (__private::div_overflows(primitive_value, rhs.primitive_value)) [[unlikely]] return Option<i64>(); else return Option<i64>::with( static_cast<int64_t>(primitive_value % rhs.primitive_value)); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i64, bool>> __attribute__((pure)) constexpr Tuple overflowing_rem(const i64& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0); if (__private::div_overflows_nonzero(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)) [[unlikely]] { return Tuple::with(int64_t{0}, true); } else { return Tuple::with( static_cast<int64_t>(primitive_value % rhs.primitive_value), false); } } __attribute__((pure)) constexpr i64 wrapping_rem(const i64& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0); if (__private::div_overflows_nonzero(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)) [[likely]] { return int64_t{0}; } else { return static_cast<int64_t>(primitive_value % rhs.primitive_value); } } __attribute__((pure)) constexpr i64 div_euclid(const i64& rhs) const& noexcept { ::sus::check(!__private::div_overflows(primitive_value, rhs.primitive_value)); return __private::div_euclid(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value); } __attribute__((pure)) constexpr Option<i64> checked_div_euclid( const i64& rhs) const& noexcept { if (__private::div_overflows(primitive_value, rhs.primitive_value)) [[unlikely]] { return Option<i64>(); } else { return Option<i64>::with(__private::div_euclid( ::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)); } } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i64, bool>> __attribute__((pure)) constexpr Tuple overflowing_div_euclid( const i64& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0); if (__private::div_overflows_nonzero(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)) [[unlikely]] { return Tuple::with(MIN, true); } else { return Tuple::with( __private::div_euclid(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value), false); } } __attribute__((pure)) constexpr i64 wrapping_div_euclid(const i64& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0); if (__private::div_overflows_nonzero(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)) [[unlikely]] { return MIN; } else { return __private::div_euclid(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value); } } __attribute__((pure)) constexpr i64 rem_euclid(const i64& rhs) const& noexcept { ::sus::check(!__private::div_overflows(primitive_value, rhs.primitive_value)); return __private::rem_euclid(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value); } __attribute__((pure)) constexpr Option<i64> checked_rem_euclid( const i64& rhs) const& noexcept { if (__private::div_overflows(primitive_value, rhs.primitive_value)) [[unlikely]] { return Option<i64>(); } else { return Option<i64>::with(__private::rem_euclid( ::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)); } } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i64, bool>> __attribute__((pure)) constexpr Tuple overflowing_rem_euclid( const i64& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0); if (__private::div_overflows_nonzero(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)) [[unlikely]] { return Tuple::with(int64_t{0}, true); } else { return Tuple::with( __private::rem_euclid(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value), false); } } __attribute__((pure)) constexpr i64 wrapping_rem_euclid(const i64& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0); if (__private::div_overflows_nonzero(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)) [[unlikely]] { return int64_t{0}; } else { return __private::rem_euclid(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value); } } __attribute__((pure)) constexpr Option<i64> checked_shl(const u32& rhs) const& noexcept { const auto out = __private::shl_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return Option<i64>::with(out.value); else return Option<i64>(); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i64, bool>> __attribute__((pure)) constexpr Tuple overflowing_shl(const u32& rhs) const& noexcept { const auto out = __private::shl_with_overflow(primitive_value, rhs.primitive_value); return Tuple::with(out.value, out.overflow); } __attribute__((pure)) constexpr i64 wrapping_shl(const u32& rhs) const& noexcept { return __private::shl_with_overflow(primitive_value, rhs.primitive_value) .value; } __attribute__((pure)) constexpr Option<i64> checked_shr(const u32& rhs) const& noexcept { const auto out = __private::shr_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return Option<i64>::with(out.value); else return Option<i64>(); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i64, bool>> __attribute__((pure)) constexpr Tuple overflowing_shr(const u32& rhs) const& noexcept { const auto out = __private::shr_with_overflow(primitive_value, rhs.primitive_value); return Tuple::with(out.value, out.overflow); } __attribute__((pure)) constexpr i64 wrapping_shr(const u32& rhs) const& noexcept { return __private::shr_with_overflow(primitive_value, rhs.primitive_value) .value; } __attribute__((pure)) constexpr Option<i64> checked_sub(const i64& rhs) const& { const auto out = __private::sub_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return Option<i64>::with(out.value); else return Option<i64>(); } __attribute__((pure)) constexpr Option<i64> checked_sub_unsigned( const u64& rhs) const& { const auto out = __private::sub_with_overflow_unsigned(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return Option<i64>::with(out.value); else return Option<i64>(); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i64, bool>> __attribute__((pure)) constexpr Tuple overflowing_sub(const i64& rhs) const& noexcept { const auto out = __private::sub_with_overflow(primitive_value, rhs.primitive_value); return Tuple::with(out.value, out.overflow); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i64, bool>> __attribute__((pure)) constexpr Tuple overflowing_sub_unsigned( const u64& rhs) const& noexcept { const auto out = __private::sub_with_overflow_unsigned(primitive_value, rhs.primitive_value); return Tuple::with(out.value, out.overflow); } __attribute__((pure)) constexpr i64 saturating_sub(const i64& rhs) const& { return __private::saturating_sub(primitive_value, rhs.primitive_value); } __attribute__((pure)) constexpr i64 saturating_sub_unsigned(const u64& rhs) const& { const auto out = __private::sub_with_overflow_unsigned(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return out.value; else return MIN; } __attribute__((pure)) inline constexpr i64 unchecked_sub(::sus::marker::UnsafeFnMarker, const i64& rhs) const& { return static_cast<int64_t>(primitive_value - rhs.primitive_value); } constexpr i64 wrapping_sub(const i64& rhs) const& { return __private::wrapping_sub(primitive_value, rhs.primitive_value); } __attribute__((pure)) constexpr i64 wrapping_sub_unsigned(const u64& rhs) const& { return __private::sub_with_overflow_unsigned(primitive_value, rhs.primitive_value) .value; } __attribute__((pure)) constexpr u32 count_ones() const& noexcept { return __private::count_ones(__private::into_unsigned(primitive_value)); } __attribute__((pure)) constexpr u32 count_zeros() const& noexcept { return (~(*this)).count_ones(); } __attribute__((pure)) constexpr u32 leading_ones() const& noexcept { return (~(*this)).leading_zeros(); } __attribute__((pure)) constexpr u32 leading_zeros() const& noexcept { return __private::leading_zeros(__private::into_unsigned(primitive_value)); } __attribute__((pure)) constexpr u32 trailing_ones() const& noexcept { return (~(*this)).trailing_zeros(); } __attribute__((pure)) constexpr u32 trailing_zeros() const& noexcept { return __private::trailing_zeros(__private::into_unsigned(primitive_value)); } __attribute__((pure)) constexpr i64 reverse_bits() const& noexcept { return __private::into_signed( __private::reverse_bits(__private::into_unsigned(primitive_value))); } __attribute__((pure)) constexpr i64 rotate_left(const u32& n) const& noexcept { return __private::into_signed(__private::rotate_left( __private::into_unsigned(primitive_value), n.primitive_value)); } __attribute__((pure)) constexpr i64 rotate_right(const u32& n) const& noexcept { return __private::into_signed(__private::rotate_right( __private::into_unsigned(primitive_value), n.primitive_value)); } __attribute__((pure)) constexpr i64 swap_bytes() const& noexcept { return __private::into_signed( __private::swap_bytes(__private::into_unsigned(primitive_value))); } __attribute__((pure)) constexpr inline i64 pow(const u32& rhs) const& noexcept { const auto out = __private::pow_with_overflow(primitive_value, rhs.primitive_value); ::sus::check(!out.overflow); return out.value; } __attribute__((pure)) constexpr Option<i64> checked_pow(const u32& rhs) const& noexcept { const auto out = __private::pow_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return Option<i64>::with(out.value); else return Option<i64>(); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<i64, bool>> __attribute__((pure)) constexpr Tuple overflowing_pow(const u32& exp) const& noexcept { const auto out = __private::pow_with_overflow(primitive_value, exp.primitive_value); return Tuple::with(out.value, out.overflow); } __attribute__((pure)) constexpr i64 wrapping_pow(const u32& exp) const& noexcept { return __private::wrapping_pow(primitive_value, exp.primitive_value); } __attribute__((pure)) constexpr Option<u32> checked_log2() const& { if (primitive_value <= 0) [[unlikely]] { return Option<u32>(); } else { uint32_t zeros = __private::leading_zeros_nonzero( ::sus::marker::unsafe_fn, __private::into_unsigned(primitive_value)); return Option<u32>::with(BITS - 1_u32 - u32(zeros)); } } __attribute__((pure)) constexpr u32 log2() const& { return checked_log2().unwrap(); } __attribute__((pure)) constexpr Option<u32> checked_log10() const& { if (primitive_value <= 0) [[unlikely]] { return Option<u32>(); } else { return Option<u32>::with(__private::int_log10::i64(primitive_value)); } } __attribute__((pure)) constexpr u32 log10() const& { return checked_log10().unwrap(); } __attribute__((pure)) constexpr Option<u32> checked_log(const i64& base) const& noexcept { if (primitive_value <= 0 || base.primitive_value <= 1) [[unlikely]] { return Option<u32>(); } else { auto n = uint32_t{0}; auto r = primitive_value; const auto b = base.primitive_value; while (r >= b) { r /= b; n += 1u; } return Option<u32>::with(n); } } __attribute__((pure)) constexpr u32 log(const i64& base) const& noexcept { return checked_log(base).unwrap(); } __attribute__((pure)) static constexpr i64 from_be(const i64& x) noexcept { if constexpr (::sus::assertions::is_big_endian()) return x; else return x.swap_bytes(); } __attribute__((pure)) static constexpr i64 from_le(const i64& x) noexcept { if constexpr (::sus::assertions::is_little_endian()) return x; else return x.swap_bytes(); } __attribute__((pure)) constexpr i64 to_be() const& noexcept { if constexpr (::sus::assertions::is_big_endian()) return *this; else return swap_bytes(); } __attribute__((pure)) constexpr i64 to_le() const& noexcept { if constexpr (::sus::assertions::is_little_endian()) return *this; else return swap_bytes(); } __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<int64_t>()> to_be_bytes() const& noexcept; __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<int64_t>()> to_le_bytes() const& noexcept; __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<int64_t>()> to_ne_bytes() const& noexcept; __attribute__((pure)) static constexpr i64 from_be_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<int64_t>()>& bytes) noexcept; __attribute__((pure)) static constexpr i64 from_le_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<int64_t>()>& bytes) noexcept; __attribute__((pure)) static constexpr i64 from_ne_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<int64_t>()>& bytes) noexcept; }; inline constexpr i64 i64::MIN = i64(i64::MIN_PRIMITIVE); inline constexpr i64 i64::MAX = i64(i64::MAX_PRIMITIVE); inline constexpr u32 i64::BITS = u32(__private::num_bits<int64_t>()); struct isize final { ::sus::num::__private::addr_type<>::signed_type primitive_value{0}; static constexpr auto MIN_PRIMITIVE = __private::min_value< ::sus::num::__private::addr_type<>::signed_type>(); static constexpr auto MAX_PRIMITIVE = __private::max_value< ::sus::num::__private::addr_type<>::signed_type>(); static const isize MIN; static const isize MAX; static const u32 BITS; constexpr inline isize() noexcept = default; template <Signed S> requires(::sus::mem::size_of<S>() <= ::sus::mem::size_of< ::sus::num::__private::addr_type<>::signed_type>()) constexpr inline isize(S v) noexcept : primitive_value(v.primitive_value) {} template <SignedPrimitiveInteger P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of< ::sus::num::__private::addr_type<>::signed_type>()) constexpr inline isize(P v) noexcept : primitive_value(v) {} template <SignedPrimitiveEnum P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of< ::sus::num::__private::addr_type<>::signed_type>()) constexpr inline isize(P v) noexcept : primitive_value(v) {} template <SignedPrimitiveEnumClass P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of< ::sus::num::__private::addr_type<>::signed_type>()) explicit constexpr inline isize(P v) noexcept : primitive_value(static_cast< ::sus::num::__private::addr_type<>::signed_type>(v)) {} template <Unsigned U> requires(::sus::mem::size_of<U>() < ::sus::mem::size_of< ::sus::num::__private::addr_type<>::signed_type>()) constexpr inline isize(U v) noexcept : primitive_value(v.primitive_value) {} template <UnsignedPrimitiveInteger P> requires(::sus::mem::size_of<P>() < ::sus::mem::size_of< ::sus::num::__private::addr_type<>::signed_type>()) constexpr inline isize(P v) noexcept : primitive_value(v) {} template <UnsignedPrimitiveEnum P> requires(::sus::mem::size_of<P>() < ::sus::mem::size_of< ::sus::num::__private::addr_type<>::signed_type>()) constexpr inline isize(P v) noexcept : primitive_value(v) {} template <UnsignedPrimitiveEnumClass P> requires(::sus::mem::size_of<P>() < ::sus::mem::size_of< ::sus::num::__private::addr_type<>::signed_type>()) explicit constexpr inline isize(P v) noexcept : primitive_value(static_cast< ::sus::num::__private::addr_type<>::signed_type>(v)) {} template <Signed S> requires(::sus::mem::size_of<S>() <= ::sus::mem::size_of< ::sus::num::__private::addr_type<>::signed_type>()) constexpr inline isize& operator=(S v) noexcept { primitive_value = v.primitive_value; return *this; } template <SignedPrimitiveInteger P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of< ::sus::num::__private::addr_type<>::signed_type>()) constexpr inline isize& operator=(P v) noexcept { primitive_value = v; return *this; } template <SignedPrimitiveEnum P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of< ::sus::num::__private::addr_type<>::signed_type>()) constexpr inline isize& operator=(P v) noexcept { primitive_value = v; return *this; } template <Signed S> requires(::sus::mem::size_of<S>() <= ::sus::mem::size_of< ::sus::num::__private::addr_type<>::signed_type>()) __attribute__((pure)) static constexpr isize from(S s) noexcept { return isize(s); } template <Signed S> __attribute__((pure)) static constexpr ::sus::result::Result<isize, ::sus::num::TryFromIntError> try_from(S s) noexcept { using R = ::sus::result::Result<isize, ::sus::num::TryFromIntError>; if constexpr (MIN_PRIMITIVE > S::MIN_PRIMITIVE) { if (s.primitive_value < MIN_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } if constexpr (MAX_PRIMITIVE < S::MAX_PRIMITIVE) { if (s.primitive_value > MAX_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(isize(static_cast< ::sus::num::__private::addr_type<>::signed_type>(s.primitive_value))); } template <Unsigned U> __attribute__((pure)) static constexpr ::sus::result::Result<isize, ::sus::num::TryFromIntError> try_from(U u) noexcept { using R = ::sus::result::Result<isize, ::sus::num::TryFromIntError>; constexpr auto umax = __private::into_unsigned(MAX_PRIMITIVE); if constexpr (umax < U::MAX_PRIMITIVE) { if (u.primitive_value > umax) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(isize(static_cast< ::sus::num::__private::addr_type<>::signed_type>(u.primitive_value))); } template <SignedPrimitiveInteger S> requires(::sus::mem::size_of<S>() <= ::sus::mem::size_of< ::sus::num::__private::addr_type<>::signed_type>()) __attribute__((pure)) static constexpr isize from(S s) noexcept { return isize(s); } template <SignedPrimitiveInteger S> __attribute__((pure)) static constexpr ::sus::result::Result<isize, ::sus::num::TryFromIntError> try_from(S s) noexcept { using R = ::sus::result::Result<isize, ::sus::num::TryFromIntError>; if constexpr (MIN_PRIMITIVE > __private::min_value<S>()) { if (s < MIN_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } if constexpr (MAX_PRIMITIVE < __private::max_value<S>()) { if (s > MAX_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(isize(static_cast< ::sus::num::__private::addr_type<>::signed_type>(s))); } template <class S> requires((SignedPrimitiveEnum<S> || SignedPrimitiveEnumClass<S>) && ::sus::mem::size_of<S>() <= ::sus::mem::size_of< ::sus::num::__private::addr_type<>::signed_type>()) __attribute__((pure)) static constexpr isize from(S s) noexcept { using D = std::underlying_type_t<S>; return isize(static_cast<std::underlying_type_t<S>>(s)); } template <class S> requires(SignedPrimitiveEnum<S> || SignedPrimitiveEnumClass<S>) __attribute__((pure)) static constexpr ::sus::result::Result<isize, ::sus::num::TryFromIntError> try_from(S s) noexcept { using D = std::underlying_type_t<S>; using R = ::sus::result::Result<isize, ::sus::num::TryFromIntError>; if constexpr (MIN_PRIMITIVE > __private::min_value<D>()) { if (static_cast<D>(s) < MIN_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } if constexpr (MAX_PRIMITIVE < __private::max_value<D>()) { if (static_cast<D>(s) > MAX_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(isize(static_cast< ::sus::num::__private::addr_type<>::signed_type>(s))); } template <UnsignedPrimitiveInteger U> __attribute__((pure)) static constexpr ::sus::result::Result<isize, ::sus::num::TryFromIntError> try_from(U u) noexcept { using R = ::sus::result::Result<isize, ::sus::num::TryFromIntError>; constexpr auto umax = __private::into_unsigned(MAX_PRIMITIVE); if constexpr (umax < __private::max_value<U>()) { if (u > umax) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(isize(static_cast< ::sus::num::__private::addr_type<>::signed_type>(u))); } template <class U> requires(UnsignedPrimitiveEnum<U> || UnsignedPrimitiveEnumClass<U>) __attribute__((pure)) static constexpr ::sus::result::Result<isize, ::sus::num::TryFromIntError> try_from(U u) noexcept { using D = std::underlying_type_t<U>; using R = ::sus::result::Result<isize, ::sus::num::TryFromIntError>; constexpr auto umax = __private::into_unsigned(MAX_PRIMITIVE); if constexpr (umax < __private::max_value<D>()) { if (static_cast<D>(u) > umax) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(isize(static_cast< ::sus::num::__private::addr_type<>::signed_type>(u))); } static constexpr isize from_product( ::sus::iter::Iterator<isize> auto&& it) noexcept { auto p = isize(::sus::num::__private::addr_type<>::signed_type{1}); for (isize i : ::sus::move(it)) p *= i; return p; } static constexpr isize from_sum( ::sus::iter::Iterator<isize> auto&& it) noexcept { auto p = isize(::sus::num::__private::addr_type<>::signed_type{0}); for (isize i : ::sus::move(it)) p += i; return p; } template <SignedPrimitiveInteger U> requires(::sus::mem::size_of<U>() >= ::sus::mem::size_of< ::sus::num::__private::addr_type<>::signed_type>()) __attribute__((pure)) constexpr inline explicit operator U() const { return primitive_value; } __attribute__((pure)) constexpr bool is_negative() const& noexcept { return primitive_value < 0; } __attribute__((pure)) constexpr bool is_positive() const& noexcept { return primitive_value > 0; } __attribute__((pure)) constexpr isize signum() const& noexcept { if (primitive_value < 0) return ::sus::num::__private::addr_type<>::signed_type{-1}; else return ::sus::num::__private::addr_type<>::signed_type{primitive_value != 0}; } [[nodiscard]] __attribute__((pure)) friend constexpr inline bool operator==( const isize& l, const isize& r) noexcept = default; template <SignedPrimitiveInteger P> [[nodiscard]] __attribute__((pure)) friend constexpr inline bool operator==( const isize& l, const P& r) noexcept { return l.primitive_value == r; } template <Signed S> [[nodiscard]] __attribute__((pure)) friend constexpr inline bool operator==( const isize& l, const S& r) noexcept { return l.primitive_value == r.primitive_value; } template <UnsignedPrimitiveInteger P> [[nodiscard]] __attribute__((pure)) friend constexpr inline std::strong_ordering operator<=>( const isize& l, const isize& r) noexcept { return l.primitive_value <=> r.primitive_value; } template <SignedPrimitiveInteger P> [[nodiscard]] __attribute__((pure)) friend constexpr inline std::strong_ordering operator<=>( const isize& l, const P& r) noexcept { return l.primitive_value <=> r; } template <Signed S> [[nodiscard]] __attribute__((pure)) friend constexpr inline std::strong_ordering operator<=>( const isize& l, const S& r) noexcept { return l.primitive_value <=> r.primitive_value; } __attribute__((pure)) constexpr inline isize operator-() const& noexcept { ::sus::check(primitive_value != MIN_PRIMITIVE); return __private::unchecked_neg(primitive_value); } __attribute__((pure)) constexpr inline isize operator~() const& noexcept { return __private::into_signed( __private::unchecked_not(__private::into_unsigned(primitive_value))); } [[nodiscard]] __attribute__((pure)) friend constexpr inline isize operator+( const isize& l, const isize& r) noexcept { const auto out = __private::add_with_overflow(l.primitive_value, r.primitive_value); ::sus::check(!out.overflow); return out.value; } [[nodiscard]] __attribute__((pure)) friend constexpr inline isize operator-( const isize& l, const isize& r) noexcept { const auto out = __private::sub_with_overflow(l.primitive_value, r.primitive_value); ::sus::check(!out.overflow); return out.value; } [[nodiscard]] __attribute__((pure)) friend constexpr inline isize operator*( const isize& l, const isize& r) noexcept { const auto out = __private::mul_with_overflow(l.primitive_value, r.primitive_value); ::sus::check(!out.overflow); return out.value; } [[nodiscard]] __attribute__((pure)) friend constexpr inline isize operator/( const isize& l, const isize& r) noexcept { ::sus::check(r.primitive_value != 0); ::sus::check(l.primitive_value != MIN_PRIMITIVE || r.primitive_value != -1); return static_cast< ::sus::num::__private::addr_type<>::signed_type>(l.primitive_value / r.primitive_value); } [[nodiscard]] __attribute__((pure)) friend constexpr inline isize operator%( const isize& l, const isize& r) noexcept { ::sus::check(r.primitive_value != 0); ::sus::check(l.primitive_value != MIN_PRIMITIVE || r.primitive_value != -1); return static_cast< ::sus::num::__private::addr_type<>::signed_type>(l.primitive_value % r.primitive_value); } [[nodiscard]] __attribute__((pure)) friend constexpr inline isize operator&( const isize& l, const isize& r) noexcept { return static_cast< ::sus::num::__private::addr_type<>::signed_type>(l.primitive_value & r.primitive_value); } [[nodiscard]] __attribute__((pure)) friend constexpr inline isize operator|( const isize& l, const isize& r) noexcept { return static_cast< ::sus::num::__private::addr_type<>::signed_type>(l.primitive_value | r.primitive_value); } [[nodiscard]] __attribute__((pure)) friend constexpr inline isize operator^( const isize& l, const isize& r) noexcept { return static_cast< ::sus::num::__private::addr_type<>::signed_type>(l.primitive_value ^ r.primitive_value); } [[nodiscard]] __attribute__((pure)) friend constexpr inline isize operator<<( const isize& l, const u32& r) noexcept { const auto out = __private::shl_with_overflow(l.primitive_value, r.primitive_value); ::sus::check(!out.overflow); return out.value; } [[nodiscard]] __attribute__((pure)) friend constexpr inline isize operator>>( const isize& l, const u32& r) noexcept { const auto out = __private::shr_with_overflow(l.primitive_value, r.primitive_value); ::sus::check(!out.overflow); return out.value; } constexpr inline void operator+=(isize r) & noexcept { const auto out = __private::add_with_overflow(primitive_value, r.primitive_value); ::sus::check(!out.overflow); primitive_value = out.value; } constexpr inline void operator-=(isize r) & noexcept { const auto out = __private::sub_with_overflow(primitive_value, r.primitive_value); ::sus::check(!out.overflow); primitive_value = out.value; } constexpr inline void operator*=(isize r) & noexcept { const auto out = __private::mul_with_overflow(primitive_value, r.primitive_value); ::sus::check(!out.overflow); primitive_value = out.value; } constexpr inline void operator/=(isize r) & noexcept { ::sus::check(r.primitive_value != 0); ::sus::check(primitive_value != MIN_PRIMITIVE || r.primitive_value != -1); primitive_value /= r.primitive_value; } constexpr inline void operator%=(isize r) & noexcept { ::sus::check(r.primitive_value != 0); ::sus::check(primitive_value != MIN_PRIMITIVE || r.primitive_value != -1); primitive_value %= r.primitive_value; } constexpr inline void operator&=(isize r) & noexcept { primitive_value &= r.primitive_value; } constexpr inline void operator|=(isize r) & noexcept { primitive_value |= r.primitive_value; } constexpr inline void operator^=(isize r) & noexcept { primitive_value ^= r.primitive_value; } constexpr inline void operator<<=(const u32& r) & noexcept { const auto out = __private::shl_with_overflow(primitive_value, r.primitive_value); ::sus::check(!out.overflow); primitive_value = out.value; } constexpr inline void operator>>=(const u32& r) & noexcept { const auto out = __private::shr_with_overflow(primitive_value, r.primitive_value); ::sus::check(!out.overflow); primitive_value = out.value; } __attribute__((pure)) constexpr inline isize abs() const& noexcept { ::sus::check(primitive_value != MIN_PRIMITIVE); if (primitive_value >= 0) return primitive_value; else return __private::unchecked_neg(primitive_value); } __attribute__((pure)) constexpr Option<isize> checked_abs() const& noexcept { if (primitive_value != MIN_PRIMITIVE) [[likely]] return Option<isize>::with(abs()); else return Option<isize>(); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<isize, bool>> __attribute__((pure)) constexpr Tuple overflowing_abs() const& noexcept { if (primitive_value != MIN_PRIMITIVE) [[likely]] return Tuple::with(abs(), false); else return Tuple::with(MIN, true); } __attribute__((pure)) constexpr isize saturating_abs() const& noexcept { if (primitive_value != MIN_PRIMITIVE) [[likely]] return abs(); else return MAX; } __attribute__((pure)) constexpr usize unsigned_abs() const& noexcept { if (primitive_value >= 0) { return __private::into_unsigned(primitive_value); } else { const auto neg_plus_one = __private::unchecked_add(primitive_value, ::sus::num::__private::addr_type<>::signed_type{1}); const auto pos_minus_one = __private::into_unsigned(__private::unchecked_neg(neg_plus_one)); return __private::unchecked_add(pos_minus_one, decltype(pos_minus_one){1}); } } __attribute__((pure)) constexpr isize wrapping_abs() const& noexcept { if (primitive_value != MIN_PRIMITIVE) [[likely]] return abs(); else return MIN; } __attribute__((pure)) constexpr usize abs_diff(const isize& r) const& noexcept { if (primitive_value >= r.primitive_value) { return __private::sub_with_unsigned_positive_result(primitive_value, r.primitive_value); } else { return __private::sub_with_unsigned_positive_result(r.primitive_value, primitive_value); } } __attribute__((pure)) constexpr Option<isize> checked_add(const isize& rhs) const& noexcept { const auto out = __private::add_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return Option<isize>::with(out.value); else return Option<isize>(); } __attribute__((pure)) constexpr Option<isize> checked_add_unsigned( const usize& rhs) const& noexcept { const auto out = __private::add_with_overflow_unsigned(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return Option<isize>::with(out.value); else return Option<isize>(); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<isize, bool>> __attribute__((pure)) constexpr Tuple overflowing_add(const isize& rhs) const& noexcept { const auto r = __private::add_with_overflow(primitive_value, rhs.primitive_value); return Tuple::with(r.value, r.overflow); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<isize, bool>> __attribute__((pure)) constexpr Tuple overflowing_add_unsigned( const usize& rhs) const& noexcept { const auto r = __private::add_with_overflow_unsigned(primitive_value, rhs.primitive_value); return Tuple::with(r.value, r.overflow); } __attribute__((pure)) constexpr isize saturating_add(const isize& rhs) const& noexcept { return __private::saturating_add(primitive_value, rhs.primitive_value); } __attribute__((pure)) constexpr isize saturating_add_unsigned( const usize& rhs) const& noexcept { const auto r = __private::add_with_overflow_unsigned(primitive_value, rhs.primitive_value); if (!r.overflow) [[likely]] return r.value; else return MAX; } __attribute__((pure)) inline constexpr isize unchecked_add( ::sus::marker::UnsafeFnMarker, const isize& rhs) const& noexcept { return __private::unchecked_add(primitive_value, rhs.primitive_value); } __attribute__((pure)) constexpr isize wrapping_add(const isize& rhs) const& noexcept { return __private::wrapping_add(primitive_value, rhs.primitive_value); } __attribute__((pure)) constexpr isize wrapping_add_unsigned( const usize& rhs) const& noexcept { return __private::add_with_overflow_unsigned(primitive_value, rhs.primitive_value) .value; } __attribute__((pure)) constexpr Option<isize> checked_div(const isize& rhs) const& noexcept { if (__private::div_overflows(primitive_value, rhs.primitive_value)) [[unlikely]] return Option<isize>(); else return Option<isize>::with( __private::unchecked_div(primitive_value, rhs.primitive_value)); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<isize, bool>> __attribute__((pure)) constexpr Tuple overflowing_div(const isize& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0); if (__private::div_overflows_nonzero(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)) [[unlikely]] { return Tuple::with(MIN, true); } else { return Tuple::with( __private::unchecked_div(primitive_value, rhs.primitive_value), false); } } __attribute__((pure)) constexpr isize saturating_div(const isize& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0); if (__private::div_overflows_nonzero(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)) [[unlikely]] { return MAX; } else { return __private::unchecked_div(primitive_value, rhs.primitive_value); } } __attribute__((pure)) constexpr isize wrapping_div(const isize& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0); if (__private::div_overflows_nonzero(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)) [[unlikely]] { return MIN; } else { return __private::unchecked_div(primitive_value, rhs.primitive_value); } } __attribute__((pure)) constexpr Option<isize> checked_mul(const isize& rhs) const& noexcept { const auto out = __private::mul_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return Option<isize>::with(out.value); else return Option<isize>(); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<isize, bool>> __attribute__((pure)) constexpr Tuple overflowing_mul(const isize& rhs) const& noexcept { const auto out = __private::mul_with_overflow(primitive_value, rhs.primitive_value); return Tuple::with(out.value, out.overflow); } __attribute__((pure)) constexpr isize saturating_mul(const isize& rhs) const& noexcept { return __private::saturating_mul(primitive_value, rhs.primitive_value); } __attribute__((pure)) constexpr inline isize unchecked_mul( ::sus::marker::UnsafeFnMarker, const isize& rhs) const& noexcept { return __private::unchecked_mul(primitive_value, rhs.primitive_value); } __attribute__((pure)) constexpr isize wrapping_mul(const isize& rhs) const& noexcept { return __private::wrapping_mul(primitive_value, rhs.primitive_value); } __attribute__((pure)) constexpr Option<isize> checked_neg() const& noexcept { if (primitive_value != MIN_PRIMITIVE) [[likely]] return Option<isize>::with(__private::unchecked_neg(primitive_value)); else return Option<isize>(); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<isize, bool>> __attribute__((pure)) constexpr Tuple overflowing_neg() const& noexcept { if (primitive_value != MIN_PRIMITIVE) [[likely]] return Tuple::with(__private::unchecked_neg(primitive_value), false); else return Tuple::with(MIN, true); } __attribute__((pure)) constexpr isize saturating_neg() const& noexcept { if (primitive_value != MIN_PRIMITIVE) [[likely]] return __private::unchecked_neg(primitive_value); else return MAX; } __attribute__((pure)) constexpr isize wrapping_neg() const& noexcept { if (primitive_value != MIN_PRIMITIVE) [[likely]] return __private::unchecked_neg(primitive_value); else return MIN; } __attribute__((pure)) constexpr Option<isize> checked_rem(const isize& rhs) const& noexcept { if (__private::div_overflows(primitive_value, rhs.primitive_value)) [[unlikely]] return Option<isize>(); else return Option<isize>::with( static_cast< ::sus::num::__private::addr_type<>::signed_type>(primitive_value % rhs.primitive_value)); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<isize, bool>> __attribute__((pure)) constexpr Tuple overflowing_rem(const isize& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0); if (__private::div_overflows_nonzero(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)) [[unlikely]] { return Tuple::with(::sus::num::__private::addr_type<>::signed_type{0}, true); } else { return Tuple::with( static_cast< ::sus::num::__private::addr_type<>::signed_type>(primitive_value % rhs.primitive_value), false); } } __attribute__((pure)) constexpr isize wrapping_rem(const isize& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0); if (__private::div_overflows_nonzero(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)) [[likely]] { return ::sus::num::__private::addr_type<>::signed_type{0}; } else { return static_cast< ::sus::num::__private::addr_type<>::signed_type>(primitive_value % rhs.primitive_value); } } __attribute__((pure)) constexpr isize div_euclid(const isize& rhs) const& noexcept { ::sus::check(!__private::div_overflows(primitive_value, rhs.primitive_value)); return __private::div_euclid(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value); } __attribute__((pure)) constexpr Option<isize> checked_div_euclid( const isize& rhs) const& noexcept { if (__private::div_overflows(primitive_value, rhs.primitive_value)) [[unlikely]] { return Option<isize>(); } else { return Option<isize>::with(__private::div_euclid( ::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)); } } template <int&..., class Tuple = ::sus::tuple_type::Tuple<isize, bool>> __attribute__((pure)) constexpr Tuple overflowing_div_euclid( const isize& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0); if (__private::div_overflows_nonzero(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)) [[unlikely]] { return Tuple::with(MIN, true); } else { return Tuple::with( __private::div_euclid(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value), false); } } __attribute__((pure)) constexpr isize wrapping_div_euclid(const isize& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0); if (__private::div_overflows_nonzero(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)) [[unlikely]] { return MIN; } else { return __private::div_euclid(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value); } } __attribute__((pure)) constexpr isize rem_euclid(const isize& rhs) const& noexcept { ::sus::check(!__private::div_overflows(primitive_value, rhs.primitive_value)); return __private::rem_euclid(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value); } __attribute__((pure)) constexpr Option<isize> checked_rem_euclid( const isize& rhs) const& noexcept { if (__private::div_overflows(primitive_value, rhs.primitive_value)) [[unlikely]] { return Option<isize>(); } else { return Option<isize>::with(__private::rem_euclid( ::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)); } } template <int&..., class Tuple = ::sus::tuple_type::Tuple<isize, bool>> __attribute__((pure)) constexpr Tuple overflowing_rem_euclid( const isize& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0); if (__private::div_overflows_nonzero(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)) [[unlikely]] { return Tuple::with(::sus::num::__private::addr_type<>::signed_type{0}, true); } else { return Tuple::with( __private::rem_euclid(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value), false); } } __attribute__((pure)) constexpr isize wrapping_rem_euclid(const isize& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0); if (__private::div_overflows_nonzero(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value)) [[unlikely]] { return ::sus::num::__private::addr_type<>::signed_type{0}; } else { return __private::rem_euclid(::sus::marker::unsafe_fn, primitive_value, rhs.primitive_value); } } __attribute__((pure)) constexpr Option<isize> checked_shl(const u32& rhs) const& noexcept { const auto out = __private::shl_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return Option<isize>::with(out.value); else return Option<isize>(); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<isize, bool>> __attribute__((pure)) constexpr Tuple overflowing_shl(const u32& rhs) const& noexcept { const auto out = __private::shl_with_overflow(primitive_value, rhs.primitive_value); return Tuple::with(out.value, out.overflow); } __attribute__((pure)) constexpr isize wrapping_shl(const u32& rhs) const& noexcept { return __private::shl_with_overflow(primitive_value, rhs.primitive_value) .value; } __attribute__((pure)) constexpr Option<isize> checked_shr(const u32& rhs) const& noexcept { const auto out = __private::shr_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return Option<isize>::with(out.value); else return Option<isize>(); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<isize, bool>> __attribute__((pure)) constexpr Tuple overflowing_shr(const u32& rhs) const& noexcept { const auto out = __private::shr_with_overflow(primitive_value, rhs.primitive_value); return Tuple::with(out.value, out.overflow); } __attribute__((pure)) constexpr isize wrapping_shr(const u32& rhs) const& noexcept { return __private::shr_with_overflow(primitive_value, rhs.primitive_value) .value; } __attribute__((pure)) constexpr Option<isize> checked_sub(const isize& rhs) const& { const auto out = __private::sub_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return Option<isize>::with(out.value); else return Option<isize>(); } __attribute__((pure)) constexpr Option<isize> checked_sub_unsigned( const usize& rhs) const& { const auto out = __private::sub_with_overflow_unsigned(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return Option<isize>::with(out.value); else return Option<isize>(); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<isize, bool>> __attribute__((pure)) constexpr Tuple overflowing_sub(const isize& rhs) const& noexcept { const auto out = __private::sub_with_overflow(primitive_value, rhs.primitive_value); return Tuple::with(out.value, out.overflow); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<isize, bool>> __attribute__((pure)) constexpr Tuple overflowing_sub_unsigned( const usize& rhs) const& noexcept { const auto out = __private::sub_with_overflow_unsigned(primitive_value, rhs.primitive_value); return Tuple::with(out.value, out.overflow); } __attribute__((pure)) constexpr isize saturating_sub(const isize& rhs) const& { return __private::saturating_sub(primitive_value, rhs.primitive_value); } __attribute__((pure)) constexpr isize saturating_sub_unsigned(const usize& rhs) const& { const auto out = __private::sub_with_overflow_unsigned(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return out.value; else return MIN; } __attribute__((pure)) inline constexpr isize unchecked_sub(::sus::marker::UnsafeFnMarker, const isize& rhs) const& { return static_cast< ::sus::num::__private::addr_type<>::signed_type>(primitive_value - rhs.primitive_value); } constexpr isize wrapping_sub(const isize& rhs) const& { return __private::wrapping_sub(primitive_value, rhs.primitive_value); } __attribute__((pure)) constexpr isize wrapping_sub_unsigned(const usize& rhs) const& { return __private::sub_with_overflow_unsigned(primitive_value, rhs.primitive_value) .value; } __attribute__((pure)) constexpr u32 count_ones() const& noexcept { return __private::count_ones(__private::into_unsigned(primitive_value)); } __attribute__((pure)) constexpr u32 count_zeros() const& noexcept { return (~(*this)).count_ones(); } __attribute__((pure)) constexpr u32 leading_ones() const& noexcept { return (~(*this)).leading_zeros(); } __attribute__((pure)) constexpr u32 leading_zeros() const& noexcept { return __private::leading_zeros(__private::into_unsigned(primitive_value)); } __attribute__((pure)) constexpr u32 trailing_ones() const& noexcept { return (~(*this)).trailing_zeros(); } __attribute__((pure)) constexpr u32 trailing_zeros() const& noexcept { return __private::trailing_zeros(__private::into_unsigned(primitive_value)); } __attribute__((pure)) constexpr isize reverse_bits() const& noexcept { return __private::into_signed( __private::reverse_bits(__private::into_unsigned(primitive_value))); } __attribute__((pure)) constexpr isize rotate_left(const u32& n) const& noexcept { return __private::into_signed(__private::rotate_left( __private::into_unsigned(primitive_value), n.primitive_value)); } __attribute__((pure)) constexpr isize rotate_right(const u32& n) const& noexcept { return __private::into_signed(__private::rotate_right( __private::into_unsigned(primitive_value), n.primitive_value)); } __attribute__((pure)) constexpr isize swap_bytes() const& noexcept { return __private::into_signed( __private::swap_bytes(__private::into_unsigned(primitive_value))); } __attribute__((pure)) constexpr inline isize pow(const u32& rhs) const& noexcept { const auto out = __private::pow_with_overflow(primitive_value, rhs.primitive_value); ::sus::check(!out.overflow); return out.value; } __attribute__((pure)) constexpr Option<isize> checked_pow(const u32& rhs) const& noexcept { const auto out = __private::pow_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return Option<isize>::with(out.value); else return Option<isize>(); } template <int&..., class Tuple = ::sus::tuple_type::Tuple<isize, bool>> __attribute__((pure)) constexpr Tuple overflowing_pow(const u32& exp) const& noexcept { const auto out = __private::pow_with_overflow(primitive_value, exp.primitive_value); return Tuple::with(out.value, out.overflow); } __attribute__((pure)) constexpr isize wrapping_pow(const u32& exp) const& noexcept { return __private::wrapping_pow(primitive_value, exp.primitive_value); } __attribute__((pure)) constexpr Option<u32> checked_log2() const& { if (primitive_value <= 0) [[unlikely]] { return Option<u32>(); } else { uint32_t zeros = __private::leading_zeros_nonzero( ::sus::marker::unsafe_fn, __private::into_unsigned(primitive_value)); return Option<u32>::with(BITS - 1_u32 - u32(zeros)); } } __attribute__((pure)) constexpr u32 log2() const& { return checked_log2().unwrap(); } __attribute__((pure)) constexpr Option<u32> checked_log10() const& { if (primitive_value <= 0) [[unlikely]] { return Option<u32>(); } else { return Option<u32>::with(__private::int_log10::isize(primitive_value)); } } __attribute__((pure)) constexpr u32 log10() const& { return checked_log10().unwrap(); } __attribute__((pure)) constexpr Option<u32> checked_log(const isize& base) const& noexcept { if (primitive_value <= 0 || base.primitive_value <= 1) [[unlikely]] { return Option<u32>(); } else { auto n = uint32_t{0}; auto r = primitive_value; const auto b = base.primitive_value; while (r >= b) { r /= b; n += 1u; } return Option<u32>::with(n); } } __attribute__((pure)) constexpr u32 log(const isize& base) const& noexcept { return checked_log(base).unwrap(); } __attribute__((pure)) static constexpr isize from_be(const isize& x) noexcept { if constexpr (::sus::assertions::is_big_endian()) return x; else return x.swap_bytes(); } __attribute__((pure)) static constexpr isize from_le(const isize& x) noexcept { if constexpr (::sus::assertions::is_little_endian()) return x; else return x.swap_bytes(); } __attribute__((pure)) constexpr isize to_be() const& noexcept { if constexpr (::sus::assertions::is_big_endian()) return *this; else return swap_bytes(); } __attribute__((pure)) constexpr isize to_le() const& noexcept { if constexpr (::sus::assertions::is_little_endian()) return *this; else return swap_bytes(); } __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of< ::sus::num::__private::addr_type<>::signed_type>()> to_be_bytes() const& noexcept; __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of< ::sus::num::__private::addr_type<>::signed_type>()> to_le_bytes() const& noexcept; __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of< ::sus::num::__private::addr_type<>::signed_type>()> to_ne_bytes() const& noexcept; __attribute__((pure)) static constexpr isize from_be_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of< ::sus::num::__private::addr_type<>::signed_type>()>& bytes) noexcept; __attribute__((pure)) static constexpr isize from_le_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of< ::sus::num::__private::addr_type<>::signed_type>()>& bytes) noexcept; __attribute__((pure)) static constexpr isize from_ne_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of< ::sus::num::__private::addr_type<>::signed_type>()>& bytes) noexcept; }; inline constexpr isize isize::MIN = isize(isize::MIN_PRIMITIVE); inline constexpr isize isize::MAX = isize(isize::MAX_PRIMITIVE); inline constexpr u32 isize::BITS = u32(__private::num_bits< ::sus::num::__private::addr_type<>::signed_type>()); template <class T> __attribute__((const)) constexpr inline T* operator+(T* t, isize offset) { return t + ptrdiff_t{offset}; } template <class T> constexpr inline T*& operator+=(T*& t, isize offset) { t += ptrdiff_t{offset}; return t; } template <class T> __attribute__((const)) constexpr inline T* operator-(T* t, isize offset) { return t - ptrdiff_t{offset}; } template <class T> constexpr inline T*& operator-=(T*& t, isize offset) { t -= ptrdiff_t{offset}; return t; } } ::sus::num::i8 inline consteval operator""_i8(unsigned long long val) { if (val > static_cast<unsigned long long>(::sus::num::i8::MAX_PRIMITIVE)) throw "Integer literal out of bounds for ##T##"; return ::sus::num::i8(static_cast<decltype(::sus::num::i8::primitive_value)>(val)); }; ::sus::num::i16 inline consteval operator""_i16(unsigned long long val) { if (val > static_cast<unsigned long long>(::sus::num::i16::MAX_PRIMITIVE)) throw "Integer literal out of bounds for ##T##"; return ::sus::num::i16(static_cast<decltype(::sus::num::i16::primitive_value)>(val)); }; ::sus::num::i32 inline consteval operator""_i32(unsigned long long val) { if (val > static_cast<unsigned long long>(::sus::num::i32::MAX_PRIMITIVE)) throw "Integer literal out of bounds for ##T##"; return ::sus::num::i32(static_cast<decltype(::sus::num::i32::primitive_value)>(val)); }; ::sus::num::i64 inline consteval operator""_i64(unsigned long long val) { if (val > static_cast<unsigned long long>(::sus::num::i64::MAX_PRIMITIVE)) throw "Integer literal out of bounds for ##T##"; return ::sus::num::i64(static_cast<decltype(::sus::num::i64::primitive_value)>(val)); }; ::sus::num::isize inline consteval operator""_isize(unsigned long long val) { if (val > static_cast<unsigned long long>(::sus::num::isize::MAX_PRIMITIVE)) throw "Integer literal out of bounds for ##T##"; return ::sus::num::isize(static_cast<decltype(::sus::num::isize::primitive_value)>(val)); }; namespace sus { using sus::num::i16; using sus::num::i32; using sus::num::i64; using sus::num::i8; using sus::num::isize; } namespace sus::ptr { template <class T> requires(!std::is_reference_v<T>) class NonNull { public: static constexpr inline NonNull with(T& t) { return NonNull(::sus::mem::addressof(t)); } template <::sus::ptr::SameOrSubclassOf<T*> U> static constexpr inline ::sus::option::Option<NonNull> with_ptr(U t) { if (t) [[likely]] return ::sus::option::Option<NonNull<T>>::with(NonNull(t)); else return ::sus::option::Option<NonNull<T>>(); } template <class U, size_t N> static constexpr inline ::sus::option::Option<NonNull> with_ptr(U (&t)[N]) = delete; template <::sus::ptr::SameOrSubclassOf<T*> U> static constexpr inline __attribute__((nonnull)) NonNull with_ptr_unchecked( ::sus::marker::UnsafeFnMarker, U t) { return NonNull(t); } template <class U, size_t N> static constexpr inline NonNull with_ptr_unchecked(U (&t)[N]) = delete; static constexpr inline NonNull from(T& t) { return with(t); } template <::sus::ptr::SameOrSubclassOf<T*> U> static constexpr inline NonNull from(U t) { ::sus::check(t); return NonNull(t); } template <class U, size_t N> static constexpr inline NonNull from(U (&t)[N]) = delete; NonNull(const NonNull&) = default; NonNull& operator=(const NonNull&) = default; const T* operator->() const { return ptr_; } T* operator->() requires(!std::is_const_v<T>) { return ptr_; } constexpr inline const T& as_ref() const { return *ptr_; } constexpr inline T& as_mut() requires(!std::is_const_v<T>) { return *ptr_; } constexpr inline const T* as_ptr() const { return ptr_; } constexpr inline T* as_mut_ptr() requires(!std::is_const_v<T>) { return ptr_; } template <class U> requires ::sus::ptr::SameOrSubclassOf<T*, U*> NonNull<U> cast() const { return NonNull<U>::with_ptr_unchecked(::sus::marker::unsafe_fn, static_cast<U*>(ptr_)); } template <class U> NonNull<U> downcast(::sus::marker::UnsafeFnMarker) const { return NonNull<U>::with_ptr_unchecked(::sus::marker::unsafe_fn, static_cast<U*>(ptr_)); } private: explicit constexpr inline NonNull( T* t) __attribute__((nonnull)) : ptr_(t) {} T* ptr_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = true; private: static_assert( std::same_as<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class> friend struct ::sus::mem::__private::NeverValueAccess; __attribute__((pure)) constexpr bool _sus_Unsafe_NeverValueIsConstructed( ::sus::marker::UnsafeFnMarker) const noexcept { static_assert( std::is_assignable_v<decltype(ptr_)&, decltype(nullptr)>, "The `never_value` must be able to be assigned to the named field."); return !(ptr_ == nullptr); } constexpr void _sus_Unsafe_NeverValueSetDestroyValue( ::sus::marker::UnsafeFnMarker) noexcept { static_assert(::sus::ops::Eq<decltype(ptr_), decltype(nullptr)>, "The `never_value` must be comparable to the named field."); ptr_ = nullptr; } static_assert(true); explicit constexpr NonNull(::sus::mem::NeverValueConstructor) noexcept : ptr_(nullptr) {} }; template <class T, class U> requires(::sus::ops::Eq<const T*, const U*>) constexpr inline bool operator==(const NonNull<T>& l, const NonNull<U>& r) noexcept { return l.as_ptr() == r.as_ptr(); } template <class T, class U> requires(::sus::ops::Ord<const T*, const U*>) constexpr inline auto operator<=>(const NonNull<T>& l, const NonNull<U>& r) noexcept { return l.as_ptr() <=> r.as_ptr(); } } namespace sus::containers { template <class ItemT> struct [[nodiscard]] SliceIter final : public ::sus::iter::IteratorBase<SliceIter<ItemT>, ItemT> { public: using Item = ItemT; private: static_assert(std::is_reference_v<Item>); static_assert(std::is_const_v<std::remove_reference_t<Item>>); using RawItem = std::remove_const_t<std::remove_reference_t<Item>>; public: static constexpr auto with(::sus::iter::IterRef ref, const RawItem* start, usize len) noexcept { const RawItem* end = start + len; ::sus::check(end >= start); return SliceIter(::sus::move(ref), start, end); } constexpr Slice<Item> as_slice() const& { return Slice<Item>::from_raw_parts(::sus::marker::unsafe_fn, ptr_, end_ - ptr_); } constexpr Option<Item> next() noexcept { if (ptr_ == end_) [[unlikely]] return Option<Item>(); return Option<Item>::with(*::sus::mem::replace(ptr_, ptr_ + 1u)); } constexpr Option<Item> next_back() noexcept { if (ptr_ == end_) [[unlikely]] return Option<Item>(); end_ -= 1u; return Option<Item>::with(*end_); } constexpr ::sus::iter::SizeHint size_hint() const noexcept { const auto remaining = exact_size_hint(); return ::sus::iter::SizeHint( remaining, ::sus::Option<::sus::num::usize>::with(remaining)); } constexpr ::sus::num::usize exact_size_hint() const noexcept { return ::sus::num::usize::try_from(end_ - ptr_) .unwrap_unchecked(::sus::marker::unsafe_fn); } private: constexpr SliceIter(::sus::iter::IterRef ref, const RawItem* start, const RawItem* end) noexcept : ref_(::sus::move(ref)), ptr_(start), end_(end) {} [[no_unique_address]] ::sus::iter::IterRef ref_; const RawItem* ptr_; const RawItem* end_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(ptr_), decltype(end_), decltype(ref_)>; static_assert(SusUnsafeTrivialRelocate, "Type is not trivially relocatable"); }; static_assert(::sus::mem::Copy<SliceIter<const i32&>>); static_assert(::sus::mem::Move<SliceIter<const i32&>>); template <class ItemT> struct SliceIterMut final : public ::sus::iter::IteratorBase<SliceIterMut<ItemT>, ItemT> { public: using Item = ItemT; private: static_assert(std::is_reference_v<Item>); static_assert(!std::is_const_v<std::remove_reference_t<Item>>); using RawItem = std::remove_reference_t<Item>; public: static constexpr auto with(::sus::iter::IterRef ref, RawItem* start, usize len) noexcept { RawItem* end = start + len; ::sus::check(end >= start); return SliceIterMut(sus::move(ref), start, end); } constexpr SliceMut<RawItem> as_mut_slice() && { return SliceMut<RawItem>::from_raw_parts_mut( ::sus::marker::unsafe_fn, ref_.to_view(), ptr_, usize::try_from(end_ - ptr_) .unwrap_unchecked(::sus::marker::unsafe_fn)); } constexpr Option<Item> next() noexcept { if (ptr_ == end_) [[unlikely]] return Option<Item>(); return Option<Item>::with(*::sus::mem::replace(ptr_, ptr_ + 1u)); } constexpr Option<Item> next_back() noexcept { if (ptr_ == end_) [[unlikely]] return Option<Item>(); end_ -= 1u; return Option<Item>::with(*end_); } constexpr ::sus::iter::SizeHint size_hint() const noexcept { const auto remaining = exact_size_hint(); return {remaining, ::sus::Option<::sus::num::usize>::with(remaining)}; } constexpr usize exact_size_hint() const noexcept { return usize::try_from(end_ - ptr_) .unwrap_unchecked(::sus::marker::unsafe_fn); } private: constexpr SliceIterMut(::sus::iter::IterRef ref, RawItem* start, RawItem* end) noexcept : ref_(::sus::move(ref)), ptr_(start), end_(end) { } [[no_unique_address]] ::sus::iter::IterRef ref_; RawItem* ptr_; RawItem* end_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(ptr_), decltype(end_), decltype(ref_)>; static_assert(SusUnsafeTrivialRelocate, "Type is not trivially relocatable"); }; static_assert(::sus::mem::Copy<SliceIterMut<i32&>>); static_assert(::sus::mem::Move<SliceIterMut<i32&>>); } namespace sus::mem { template <class T> requires(sus::mem::Move<T> && !std::is_const_v<T>) inline constexpr void swap(T& lhs, T& rhs) noexcept { if (::sus::mem::addressof(lhs) != ::sus::mem::addressof(rhs)) [[likely]] { if constexpr (::sus::mem::relocate_by_memcpy<T>) { if (!std::is_constant_evaluated()) { constexpr auto data_size = ::sus::mem::data_size_of<T>(); char temp[data_size]; ::sus::ptr::copy_nonoverlapping( ::sus::marker::unsafe_fn, reinterpret_cast<char*>(::sus::mem::addressof(lhs)), temp, data_size); ::sus::ptr::copy_nonoverlapping( ::sus::marker::unsafe_fn, reinterpret_cast<char*>(::sus::mem::addressof(rhs)), reinterpret_cast<char*>(::sus::mem::addressof(lhs)), data_size); ::sus::ptr::copy_nonoverlapping( ::sus::marker::unsafe_fn, temp, reinterpret_cast<char*>(::sus::mem::addressof(rhs)), data_size); return; } } auto temp = T(::sus::move(lhs)); lhs = ::sus::move(rhs); rhs = ::sus::move(temp); } } template <class T> requires(sus::mem::Move<T> && !std::is_const_v<T>) inline constexpr void swap_nonoverlapping(::sus::marker::UnsafeFnMarker, T& lhs, T& rhs) noexcept { if constexpr (::sus::mem::relocate_by_memcpy<T>) { if (!std::is_constant_evaluated()) { constexpr auto data_size = ::sus::mem::data_size_of<T>(); alignas(alignof(T)) char temp[data_size]; char* l = reinterpret_cast<char*>(::sus::mem::addressof(lhs)); char* r = reinterpret_cast<char*>(::sus::mem::addressof(rhs)); ::sus::ptr::copy_nonoverlapping(::sus::marker::unsafe_fn, l, temp, data_size); ::sus::ptr::copy_nonoverlapping(::sus::marker::unsafe_fn, r, l, data_size); ::sus::ptr::copy_nonoverlapping(::sus::marker::unsafe_fn, temp, r, data_size); return; } } T& l = lhs; T& r = rhs; auto temp = T(::sus::move(l)); l = ::sus::move(r); r = ::sus::move(temp); } } namespace sus::containers::__private { template <class U, class Key, class T, ::sus::fn::FnMut<Key(const T&)> KeyFn> void sort_slice_by_cached_key(const ::sus::containers::SliceMut<T>& slice, KeyFn& f) noexcept { auto indices = slice.iter() .map(f) .enumerate() .map([](::sus::Tuple<usize, Key>&& t) { auto&& [i, k] = ::sus::move(t); return ::sus::Tuple<Key, U>::with(::sus::forward<Key>(k), i); }) .collect_vec(); indices.sort_unstable(); const usize length = slice.len(); for (usize i; i < length; i += 1u) { auto index = indices[i].template at<1>(); while (index < i) { index = indices[index].template at<1>(); } indices[i].template at_mut<1>() = index; slice.swap_unchecked(::sus::marker::unsafe_fn, i, index); } }; } namespace sus::containers { template <class T> concept Concat = requires(const T& t, const ::sus::num::usize& cap) { { t.len() } -> std::same_as<::sus::num::usize>; typename T::ConcatOutputType; { T::ConcatOutputType::with_capacity(cap) } -> std::same_as<typename T::ConcatOutputType>; requires requires(typename T::ConcatOutputType & container) { { t.concat_into(container) } -> std::same_as<void>; }; }; } namespace sus::containers { template <class ItemT> struct [[nodiscard]] Chunks final : public ::sus::iter::IteratorBase<Chunks<ItemT>, ::sus::containers::Slice<ItemT>> { public: using Item = ::sus::containers::Slice<ItemT>; private: using SliceItem = ItemT; public: Option<Item> next() noexcept { if (v_.is_empty()) [[unlikely]] { return Option<Item>(); } else { auto chunksz = ::sus::ops::min(v_.len(), chunk_size_); auto [fst, snd] = v_.split_at_unchecked(::sus::marker::unsafe_fn, chunksz); v_ = snd; return Option<Item>::with(fst); } } Option<Item> next_back() noexcept { if (v_.is_empty()) [[unlikely]] { return ::sus::Option<Item>(); } else { const auto len = v_.len(); const auto remainder = len % chunk_size_; const auto chunksz = remainder != 0u ? remainder : chunk_size_; auto [fst, snd] = v_.split_at_unchecked(::sus::marker::unsafe_fn, len - chunksz); v_ = fst; return ::sus::Option<Item>::with(snd); } } ::sus::iter::SizeHint size_hint() const noexcept { const auto remaining = exact_size_hint(); return {remaining, ::sus::Option<::sus::num::usize>::with(remaining)}; } ::sus::num::usize exact_size_hint() const noexcept { if (v_.is_empty()) { return 0u; } else { ::sus::num::usize n = v_.len() / chunk_size_; ::sus::num::usize rem = v_.len() % chunk_size_; return rem > 0u ? n + 1u : n; } } private: friend class Slice<ItemT>; friend class Vec<ItemT>; template <class ArrayItemT, size_t N> friend class Array; static constexpr auto with(::sus::iter::IterRef ref, const Slice<ItemT>& values, ::sus::num::usize chunk_size) noexcept { ::sus::check(chunk_size > 0u); return Chunks(::sus::move(ref), values, chunk_size); } constexpr Chunks(::sus::iter::IterRef ref, const Slice<ItemT>& values, ::sus::num::usize chunk_size) noexcept : ref_(::sus::move(ref)), v_(values), chunk_size_(chunk_size) {} [[no_unique_address]] ::sus::iter::IterRef ref_; Slice<ItemT> v_; ::sus::num::usize chunk_size_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(ref_), decltype(v_), decltype(chunk_size_)>; static_assert(SusUnsafeTrivialRelocate, "Type is not trivially relocatable"); }; template <class ItemT> struct [[nodiscard]] ChunksMut final : public ::sus::iter::IteratorBase<ChunksMut<ItemT>, ::sus::containers::SliceMut<ItemT>> { public: using Item = ::sus::containers::SliceMut<ItemT>; private: static_assert(!std::is_reference_v<ItemT>); static_assert(!std::is_const_v<ItemT>); using SliceItem = ItemT; public: Option<Item> next() noexcept { if (v_.is_empty()) [[unlikely]] { return Option<Item>(); } else { const auto chunksz = ::sus::ops::min(v_.len(), chunk_size_); auto [fst, snd] = v_.split_at_mut_unchecked(::sus::marker::unsafe_fn, chunksz); v_ = snd; return Option<SliceMut<ItemT>>::with(fst); } } Option<Item> next_back() noexcept { if (v_.is_empty()) [[unlikely]] { return ::sus::Option<Item>(); } else { const auto len = v_.len(); const auto remainder = len % chunk_size_; const auto chunksz = remainder != 0u ? remainder : chunk_size_; auto [fst, snd] = v_.split_at_mut_unchecked(::sus::marker::unsafe_fn, len - chunksz); v_ = fst; return ::sus::Option<Item>::with(snd); } } ::sus::iter::SizeHint size_hint() const noexcept { const auto remaining = exact_size_hint(); return {remaining, ::sus::Option<::sus::num::usize>::with(remaining)}; } ::sus::num::usize exact_size_hint() const noexcept { if (v_.is_empty()) { return 0u; } else { const auto n = v_.len() / chunk_size_; const auto rem = v_.len() % chunk_size_; return rem > 0u ? n + 1u : n; } } private: friend class SliceMut<ItemT>; friend class Vec<ItemT>; template <class ArrayItemT, size_t N> friend class Array; static constexpr auto with(::sus::iter::IterRef ref, const SliceMut<ItemT>& values, ::sus::num::usize chunk_size) noexcept { ::sus::check(chunk_size > 0u); return ChunksMut(::sus::move(ref), values, chunk_size); } constexpr ChunksMut(::sus::iter::IterRef ref, const SliceMut<ItemT>& values, ::sus::num::usize chunk_size) noexcept : ref_(::sus::move(ref)), v_(values), chunk_size_(chunk_size) {} [[no_unique_address]] ::sus::iter::IterRef ref_; SliceMut<ItemT> v_; ::sus::num::usize chunk_size_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(ref_), decltype(v_), decltype(chunk_size_)>; static_assert(SusUnsafeTrivialRelocate, "Type is not trivially relocatable"); }; template <class ItemT> struct [[nodiscard]] ChunksExact final : public ::sus::iter::IteratorBase<ChunksExact<ItemT>, ::sus::containers::Slice<ItemT>> { public: using Item = ::sus::containers::Slice<ItemT>; private: using SliceItem = ItemT; public: [[nodiscard]] Item remainder() const& { return rem_; } constexpr Option<Item> next() noexcept { if (v_.len() < chunk_size_) [[unlikely]] { return Option<Item>(); } else { auto [fst, snd] = v_.split_at_unchecked(::sus::marker::unsafe_fn, chunk_size_); v_ = ::sus::move(snd); return Option<Item>::with(::sus::move(fst)); } } constexpr Option<Item> next_back() noexcept { if (v_.len() < chunk_size_) [[unlikely]] { return ::sus::Option<Item>(); } else { auto [fst, snd] = v_.split_at_unchecked( ::sus::marker::unsafe_fn, v_.len().unchecked_sub(::sus::marker::unsafe_fn, chunk_size_)); v_ = ::sus::move(fst); return ::sus::Option<Item>::with(::sus::move(snd)); } } constexpr ::sus::iter::SizeHint size_hint() const noexcept { const auto remaining = exact_size_hint(); return {remaining, ::sus::Option<::sus::num::usize>::with(remaining)}; } constexpr ::sus::num::usize exact_size_hint() const noexcept { return v_.len() / chunk_size_; } private: friend class Slice<ItemT>; friend class Vec<ItemT>; template <class ArrayItemT, size_t N> friend class Array; static constexpr auto with(::sus::iter::IterRef ref, const Slice<ItemT>& values, ::sus::num::usize chunk_size) noexcept { ::sus::check(chunk_size > 0u); auto rem = values.len() % chunk_size; auto fst_len = values.len().unchecked_sub(::sus::marker::unsafe_fn, rem); auto [fst, snd] = values.split_at_unchecked(::sus::marker::unsafe_fn, fst_len); return ChunksExact(::sus::move(ref), fst, snd, chunk_size); } constexpr ChunksExact(::sus::iter::IterRef ref, const Slice<ItemT>& values, const Slice<ItemT>& remainder, ::sus::num::usize chunk_size) noexcept : ref_(::sus::move(ref)), v_(values), rem_(remainder), chunk_size_(chunk_size) {} [[no_unique_address]] ::sus::iter::IterRef ref_; Slice<ItemT> v_; Slice<ItemT> rem_; ::sus::num::usize chunk_size_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(ref_), decltype(v_), decltype(rem_), decltype(chunk_size_)>; static_assert(SusUnsafeTrivialRelocate, "Type is not trivially relocatable"); }; template <class ItemT> struct [[nodiscard]] ChunksExactMut final : public ::sus::iter::IteratorBase<ChunksExactMut<ItemT>, ::sus::containers::SliceMut<ItemT>> { public: using Item = ::sus::containers::SliceMut<ItemT>; private: using SliceItem = ItemT; public: [[nodiscard]] constexpr Item remainder() const& { return rem_; } constexpr Option<Item> next() noexcept { if (v_.len() < chunk_size_) [[unlikely]] { return Option<Item>(); } else { auto [fst, snd] = v_.split_at_mut_unchecked(::sus::marker::unsafe_fn, chunk_size_); v_ = snd; return Option<Item>::with(fst); } } constexpr Option<Item> next_back() noexcept { if (v_.len() < chunk_size_) [[unlikely]] { return ::sus::Option<Item>(); } else { auto [fst, snd] = v_.split_at_mut_unchecked( ::sus::marker::unsafe_fn, v_.len().unchecked_sub(::sus::marker::unsafe_fn, chunk_size_)); v_ = fst; return ::sus::Option<Item>::with(snd); } } constexpr ::sus::iter::SizeHint size_hint() const noexcept { const auto remaining = exact_size_hint(); return {remaining, ::sus::Option<::sus::num::usize>::with(remaining)}; } constexpr ::sus::num::usize exact_size_hint() const noexcept { return v_.len() / chunk_size_; } private: friend class SliceMut<ItemT>; friend class Vec<ItemT>; template <class ArrayItemT, size_t N> friend class Array; static constexpr auto with(::sus::iter::IterRef ref, const SliceMut<ItemT>& values, ::sus::num::usize chunk_size) noexcept { ::sus::check(chunk_size > 0u); auto rem = values.len() % chunk_size; auto fst_len = values.len().unchecked_sub(::sus::marker::unsafe_fn, rem); auto [fst, snd] = values.split_at_mut_unchecked(::sus::marker::unsafe_fn, fst_len); return ChunksExactMut(::sus::move(ref), fst, snd, chunk_size); } constexpr ChunksExactMut(::sus::iter::IterRef ref, const SliceMut<ItemT>& values, const SliceMut<ItemT>& remainder, ::sus::num::usize chunk_size) noexcept : ref_(::sus::move(ref)), v_(values), rem_(remainder), chunk_size_(chunk_size) {} [[no_unique_address]] ::sus::iter::IterRef ref_; SliceMut<ItemT> v_; SliceMut<ItemT> rem_; ::sus::num::usize chunk_size_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(ref_), decltype(v_), decltype(rem_), decltype(chunk_size_)>; static_assert(SusUnsafeTrivialRelocate, "Type is not trivially relocatable"); }; template <class ItemT> struct [[nodiscard]] RChunks final : public ::sus::iter::IteratorBase<RChunks<ItemT>, ::sus::containers::Slice<ItemT>> { public: using Item = ::sus::containers::Slice<ItemT>; private: using SliceItem = ItemT; public: constexpr Option<Item> next() noexcept { if (v_.is_empty()) [[unlikely]] { return Option<Item>(); } else { const auto len = v_.len(); const auto chunksz = ::sus::ops::min(len, chunk_size_); const auto mid = len.unchecked_sub(::sus::marker::unsafe_fn, chunksz); auto [fst, snd] = v_.split_at_unchecked(::sus::marker::unsafe_fn, mid); v_ = fst; return Option<Item>::with(snd); } } constexpr Option<Item> next_back() noexcept { if (v_.is_empty()) [[unlikely]] { return ::sus::Option<Item>(); } else { const auto remainder = v_.len() % chunk_size_; const auto chunksz = remainder != 0u ? remainder : chunk_size_; auto [fst, snd] = v_.split_at_unchecked(::sus::marker::unsafe_fn, chunksz); v_ = snd; return ::sus::Option<Item>::with(fst); } } constexpr ::sus::iter::SizeHint size_hint() const noexcept { const auto remaining = exact_size_hint(); return {remaining, ::sus::Option<::sus::num::usize>::with(remaining)}; } constexpr ::sus::num::usize exact_size_hint() const noexcept { if (v_.is_empty()) { return 0u; } else { ::sus::num::usize n = v_.len() / chunk_size_; ::sus::num::usize rem = v_.len() % chunk_size_; return rem > 0u ? n + 1u : n; } } private: friend class Slice<ItemT>; friend class Vec<ItemT>; template <class ArrayItemT, size_t N> friend class Array; static constexpr auto with(::sus::iter::IterRef ref, const Slice<ItemT>& values, ::sus::num::usize chunk_size) noexcept { ::sus::check(chunk_size > 0u); return RChunks(::sus::move(ref), values, chunk_size); } constexpr RChunks(::sus::iter::IterRef ref, const Slice<ItemT>& values, ::sus::num::usize chunk_size) noexcept : ref_(::sus::move(ref)), v_(values), chunk_size_(chunk_size) {} [[no_unique_address]] ::sus::iter::IterRef ref_; Slice<ItemT> v_; ::sus::num::usize chunk_size_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(ref_), decltype(v_), decltype(chunk_size_)>; static_assert(SusUnsafeTrivialRelocate, "Type is not trivially relocatable"); }; template <class ItemT> struct [[nodiscard]] RChunksMut final : public ::sus::iter::IteratorBase<RChunksMut<ItemT>, ::sus::containers::SliceMut<ItemT>> { public: using Item = ::sus::containers::SliceMut<ItemT>; private: static_assert(!std::is_reference_v<ItemT>); static_assert(!std::is_const_v<ItemT>); using SliceItem = ItemT; public: constexpr Option<Item> next() noexcept { if (v_.is_empty()) [[unlikely]] { return Option<Item>(); } else { const auto len = v_.len(); auto chunksz = ::sus::ops::min(len, chunk_size_); const auto mid = len.unchecked_sub(::sus::marker::unsafe_fn, chunksz); auto [fst, snd] = v_.split_at_mut_unchecked(::sus::marker::unsafe_fn, mid); v_ = fst; return Option<SliceMut<ItemT>>::with(snd); } } constexpr Option<Item> next_back() noexcept { if (v_.is_empty()) [[unlikely]] { return ::sus::Option<Item>(); } else { const auto remainder = v_.len() % chunk_size_; const auto chunksz = remainder != 0u ? remainder : chunk_size_; auto [fst, snd] = v_.split_at_mut_unchecked(::sus::marker::unsafe_fn, chunksz); v_ = snd; return ::sus::Option<Item>::with(fst); } } constexpr ::sus::iter::SizeHint size_hint() const noexcept { const auto remaining = exact_size_hint(); return {remaining, ::sus::Option<::sus::num::usize>::with(remaining)}; } constexpr ::sus::num::usize exact_size_hint() const noexcept { if (v_.is_empty()) { return 0u; } else { const auto n = v_.len() / chunk_size_; const auto rem = v_.len() % chunk_size_; return rem > 0u ? n + 1u : n; } } private: friend class SliceMut<ItemT>; friend class Vec<ItemT>; template <class ArrayItemT, size_t N> friend class Array; static constexpr auto with(::sus::iter::IterRef ref, const SliceMut<ItemT>& values, ::sus::num::usize chunk_size) noexcept { ::sus::check(chunk_size > 0u); return RChunksMut(::sus::move(ref), values, chunk_size); } constexpr RChunksMut(::sus::iter::IterRef ref, const SliceMut<ItemT>& values, ::sus::num::usize chunk_size) noexcept : ref_(::sus::move(ref)), v_(values), chunk_size_(chunk_size) {} [[no_unique_address]] ::sus::iter::IterRef ref_; SliceMut<ItemT> v_; ::sus::num::usize chunk_size_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(ref_), decltype(v_), decltype(chunk_size_)>; static_assert(SusUnsafeTrivialRelocate, "Type is not trivially relocatable"); }; template <class ItemT> struct [[nodiscard]] RChunksExact final : public ::sus::iter::IteratorBase<RChunksExact<ItemT>, ::sus::containers::Slice<ItemT>> { public: using Item = ::sus::containers::Slice<ItemT>; private: using SliceItem = ItemT; public: [[nodiscard]] constexpr Item remainder() const& { return rem_; } constexpr Option<Item> next() noexcept { if (v_.len() < chunk_size_) [[unlikely]] { return Option<Item>(); } else { const auto mid = v_.len().unchecked_sub(::sus::marker::unsafe_fn, chunk_size_); auto [fst, snd] = v_.split_at_unchecked(::sus::marker::unsafe_fn, mid); v_ = fst; return Option<Item>::with(snd); } } constexpr Option<Item> next_back() noexcept { if (v_.len() < chunk_size_) [[unlikely]] { return ::sus::Option<Item>(); } else { auto [fst, snd] = v_.split_at_unchecked(::sus::marker::unsafe_fn, chunk_size_); v_ = snd; return ::sus::Option<Item>::with(fst); } } constexpr ::sus::iter::SizeHint size_hint() const noexcept { const auto remaining = exact_size_hint(); return {remaining, ::sus::Option<::sus::num::usize>::with(remaining)}; } constexpr ::sus::num::usize exact_size_hint() const noexcept { return v_.len() / chunk_size_; } private: friend class Slice<ItemT>; friend class Vec<ItemT>; template <class ArrayItemT, size_t N> friend class Array; static constexpr auto with(::sus::iter::IterRef ref, const Slice<ItemT>& values, ::sus::num::usize chunk_size) noexcept { ::sus::check(chunk_size > 0u); auto rem = values.len() % chunk_size; auto [fst, snd] = values.split_at_unchecked(::sus::marker::unsafe_fn, rem); return RChunksExact(::sus::move(ref), snd, fst, chunk_size); } constexpr RChunksExact(::sus::iter::IterRef ref, const Slice<ItemT>& values, const Slice<ItemT>& remainder, ::sus::num::usize chunk_size) noexcept : ref_(::sus::move(ref)), v_(values), rem_(remainder), chunk_size_(chunk_size) {} [[no_unique_address]] ::sus::iter::IterRef ref_; Slice<ItemT> v_; Slice<ItemT> rem_; ::sus::num::usize chunk_size_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(ref_), decltype(v_), decltype(rem_), decltype(chunk_size_)>; static_assert(SusUnsafeTrivialRelocate, "Type is not trivially relocatable"); }; template <class ItemT> struct [[nodiscard]] RChunksExactMut final : public ::sus::iter::IteratorBase<RChunksExactMut<ItemT>, ::sus::containers::SliceMut<ItemT>> { public: using Item = ::sus::containers::SliceMut<ItemT>; private: using SliceItem = ItemT; public: [[nodiscard]] constexpr Item remainder() const& { return rem_; } constexpr Option<Item> next() noexcept { if (v_.len() < chunk_size_) [[unlikely]] { return Option<Item>(); } else { auto [fst, snd] = v_.split_at_mut_unchecked(::sus::marker::unsafe_fn, v_.len() - chunk_size_); v_ = fst; return Option<Item>::with(snd); } } constexpr Option<Item> next_back() noexcept { if (v_.len() < chunk_size_) [[unlikely]] { return ::sus::Option<Item>(); } else { auto [fst, snd] = v_.split_at_mut_unchecked(::sus::marker::unsafe_fn, chunk_size_); v_ = snd; return ::sus::Option<Item>::with(fst); } } constexpr ::sus::iter::SizeHint size_hint() const noexcept { const auto remaining = exact_size_hint(); return {remaining, ::sus::Option<::sus::num::usize>::with(remaining)}; } constexpr ::sus::num::usize exact_size_hint() const noexcept { return v_.len() / chunk_size_; } private: friend class SliceMut<ItemT>; friend class Vec<ItemT>; template <class ArrayItemT, size_t N> friend class Array; static constexpr auto with(::sus::iter::IterRef ref, const SliceMut<ItemT>& values, ::sus::num::usize chunk_size) noexcept { ::sus::check(chunk_size > 0u); auto rem = values.len() % chunk_size; auto [fst, snd] = values.split_at_mut_unchecked(::sus::marker::unsafe_fn, rem); return RChunksExactMut(::sus::move(ref), snd, fst, chunk_size); } constexpr RChunksExactMut(::sus::iter::IterRef ref, const SliceMut<ItemT>& values, const SliceMut<ItemT>& remainder, ::sus::num::usize chunk_size) noexcept : ref_(::sus::move(ref)), v_(values), rem_(remainder), chunk_size_(chunk_size) {} [[no_unique_address]] ::sus::iter::IterRef ref_; SliceMut<ItemT> v_; SliceMut<ItemT> rem_; ::sus::num::usize chunk_size_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(ref_), decltype(v_), decltype(rem_), decltype(chunk_size_)>; static_assert(SusUnsafeTrivialRelocate, "Type is not trivially relocatable"); }; } namespace sus::iter::__private { template <::sus::num::Integer T> constexpr T step_forward(T l) noexcept { return l + T::try_from(1).unwrap_unchecked(::sus::marker::unsafe_fn); } template <::sus::num::Integer T> constexpr T step_backward(T l) noexcept { return l - T::try_from(1).unwrap_unchecked(::sus::marker::unsafe_fn); } template <::sus::num::Integer T> constexpr ::sus::Option<T> step_forward_checked(T l) noexcept { return l.checked_add( T::try_from(1).unwrap_unchecked(::sus::marker::unsafe_fn)); } template <::sus::num::Integer T> constexpr ::sus::Option<T> step_backward_checked(T l) noexcept { return l.checked_sub( T::try_from(1).unwrap_unchecked(::sus::marker::unsafe_fn)); } template <::sus::num::Integer T> constexpr T step_forward_by(T l, ::sus::num::usize steps) noexcept { return l + T::from(steps); } template <::sus::num::Integer T> constexpr T step_backward_by(T l, ::sus::num::usize steps) noexcept { return l - T::from(steps); } template <::sus::num::Integer T> constexpr ::sus::Option<T> step_forward_by_checked( T l, ::sus::num::usize steps) noexcept { return T::try_from(steps).ok().and_then( [&l](T steps) { return l.checked_add(::sus::marker::unsafe_fn, steps); }); } template <::sus::num::Integer T> constexpr ::sus::Option<T> step_backward_by_checked( T l, ::sus::num::usize steps) noexcept { return T::try_from(steps).ok().and_then( [&l](T steps) { return l.checked_sub(::sus::marker::unsafe_fn, steps); }); } template <::sus::num::Integer T> constexpr ::sus::Option<::sus::num::usize> steps_between(const T& l, const T& r) noexcept { return r.checked_sub(l).and_then( [](T steps) { return ::sus::num::usize::try_from(steps).ok(); }); } template <class T> concept Step = requires(const T& t, ::sus::num::usize n) { { ::sus::iter::__private::step_forward(t) } -> std::same_as<T>; { ::sus::iter::__private::step_backward(t) } -> std::same_as<T>; { ::sus::iter::__private::step_forward_checked(t) } -> std::same_as<::sus::Option<T>>; { ::sus::iter::__private::step_backward_checked(t) } -> std::same_as<::sus::Option<T>>; { ::sus::iter::__private::step_forward_by(t, n) } -> std::same_as<T>; { ::sus::iter::__private::step_backward_by(t, n) } -> std::same_as<T>; { ::sus::iter::__private::step_forward_by_checked(t, n) } -> std::same_as<::sus::Option<T>>; { ::sus::iter::__private::step_backward_by_checked(t, n) } -> std::same_as<::sus::Option<T>>; { ::sus::iter::__private::steps_between(t, t) } -> std::same_as<::sus::Option<::sus::num::usize>>; }; } namespace sus::ops { template <class T, class I> concept RangeBounds = requires(const T& t, T v, I i) { { t.start_bound() } -> std::same_as<::sus::option::Option<const I&>>; { t.end_bound() } -> std::same_as<::sus::option::Option<const I&>>; requires !requires { ::sus::move(v).start_bound(); }; requires !requires { ::sus::move(v).end_bound(); }; { t.contains(i) } -> std::same_as<bool>; { ::sus::move(v).start_at(i) }; { ::sus::move(v).end_at(i) }; requires sus::mem::Copy<T> || !requires { t.start_at(i); }; requires sus::mem::Copy<T> || !requires { t.end_at(i); }; requires sus::mem::Copy<T> || !requires { v.start_at(i); }; requires sus::mem::Copy<T> || !requires { v.end_at(i); }; requires !sus::mem::Copy<T> || requires { t.start_at(i); }; requires !sus::mem::Copy<T> || requires { t.end_at(i); }; requires !sus::mem::Copy<T> || requires { v.start_at(i); }; requires !sus::mem::Copy<T> || requires { v.end_at(i); }; }; namespace __private { template <class Final, class T, bool = ::sus::iter::__private::Step<T>> class RangeIter; template <class Final, class T> class RangeIter<Final, T, true> : public ::sus::iter::IteratorBase<Final, T> { public: Option<T> next() noexcept { if (static_cast<Final*>(this)->start == static_cast<Final*>(this)->finish) return Option<T>(); return Option<T>::with( ::sus::mem::replace(static_cast<Final*>(this)->start, ::sus::iter::__private::step_forward( static_cast<Final*>(this)->start))); } ::sus::iter::SizeHint size_hint() const noexcept { Option<::sus::num::usize> steps = ::sus::iter::__private::steps_between( static_cast<const Final*>(this)->start, static_cast<const Final*>(this)->finish); const ::sus::num::usize lower = steps.is_some() ? *steps : 0_usize; return ::sus::iter::SizeHint(lower, ::sus::move(steps)); } Option<T> next_back() noexcept { if (static_cast<Final*>(this)->start == static_cast<Final*>(this)->finish) return Option<T>(); static_cast<Final*>(this)->finish = ::sus::iter::__private::step_backward( static_cast<Final*>(this)->finish); return Option<T>::with(static_cast<Final*>(this)->finish); } }; template <class Final, class T> class RangeIter<Final, T, false> {}; template <class Final, class T, bool = ::sus::iter::__private::Step<T>> class RangeFromIter; template <class Final, class T> class RangeFromIter<Final, T, true> : public ::sus::iter::IteratorBase<Final, T> { public: Option<T> next() noexcept { return Option<T>::with( ::sus::mem::replace(static_cast<Final*>(this)->start, ::sus::iter::__private::step_forward( static_cast<Final*>(this)->start))); } ::sus::iter::SizeHint size_hint() const noexcept { return ::sus::iter::SizeHint(0u, ::sus::Option<::sus::num::usize>()); } }; template <class Final, class T> class RangeFromIter<Final, T, false> {}; } template <class T> requires(::sus::ops::Ord<T>) class Range final : public __private::RangeIter<Range<T>, T> { public: T start; T finish; constexpr Range() noexcept requires(::sus::construct::Default<T>) = default; constexpr Range(T start, T finish) noexcept : start(::sus::move(start)), finish(::sus::move(finish)) {} constexpr bool contains(const T& item) const noexcept { return start <= item && item < finish; } constexpr ::sus::option::Option<const T&> start_bound() const& noexcept { return ::sus::option::Option<const T&>::with(start); } constexpr ::sus::option::Option<const T&> start_bound() && = delete; constexpr ::sus::option::Option<const T&> end_bound() const& noexcept { return ::sus::option::Option<const T&>::with(finish); } constexpr ::sus::option::Option<const T&> end_bound() && = delete; constexpr bool is_empty() const noexcept { return !(start < finish); } constexpr Range start_at(T t) const& noexcept requires(::sus::mem::Copy<T>) { return Range(::sus::move(t), finish); } constexpr Range start_at(T t) && noexcept { return Range(::sus::move(t), ::sus::move(finish)); } constexpr Range end_at(T t) const& noexcept requires(::sus::mem::Copy<T>) { return Range(start, ::sus::move(t)); } constexpr Range end_at(T t) && noexcept { return Range(::sus::move(start), ::sus::move(t)); } constexpr bool operator==(const Range& rhs) const noexcept requires Eq<T> { return start == rhs.start && finish == rhs.finish; } static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(start), decltype(finish)>; }; template <class T> requires(::sus::ops::Ord<T>) class RangeFrom final : public __private::RangeFromIter<RangeFrom<T>, T> { public: T start; constexpr RangeFrom() noexcept requires(::sus::construct::Default<T>) = default; constexpr RangeFrom(T start) noexcept : start(::sus::move(start)) {} constexpr bool contains(const T& item) const noexcept { return item >= start; } constexpr ::sus::option::Option<const T&> start_bound() const& noexcept { return ::sus::option::Option<const T&>::with(start); } constexpr ::sus::option::Option<const T&> start_bound() && = delete; constexpr ::sus::option::Option<const T&> end_bound() const& noexcept { return ::sus::option::Option<const T&>(); } constexpr ::sus::option::Option<const T&> end_bound() && = delete; constexpr RangeFrom start_at(T t) const& noexcept requires(::sus::mem::Copy<T>) { return RangeFrom(::sus::move(t)); } constexpr RangeFrom start_at(T t) && noexcept { return RangeFrom(::sus::move(t)); } constexpr Range<T> end_at(T t) const& noexcept requires(::sus::mem::Copy<T>) { return Range<T>(start, ::sus::move(t)); } constexpr Range<T> end_at(T t) && noexcept { return Range<T>(::sus::move(start), ::sus::move(t)); } constexpr bool operator==(const RangeFrom& rhs) const noexcept requires Eq<T> { return start == rhs.start; } static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(start)>; }; template <class T> requires(::sus::ops::Ord<T>) class RangeTo final { public: T finish; constexpr RangeTo() noexcept requires(::sus::construct::Default<T>) = default; constexpr RangeTo(T finish) noexcept : finish(::sus::move(finish)) {} constexpr bool contains(const T& item) const noexcept { return item < finish; } constexpr ::sus::option::Option<const T&> start_bound() const& noexcept { return ::sus::option::Option<const T&>(); } constexpr ::sus::option::Option<const T&> start_bound() && = delete; constexpr ::sus::option::Option<const T&> end_bound() const& noexcept { return ::sus::option::Option<const T&>::with(finish); } constexpr ::sus::option::Option<const T&> end_bound() && = delete; constexpr Range<T> start_at(T t) const& noexcept requires(::sus::mem::Copy<T>) { return Range<T>(::sus::move(t), finish); } constexpr Range<T> start_at(T t) && noexcept { return Range<T>(::sus::move(t), ::sus::move(finish)); } constexpr RangeTo end_at(T t) const& noexcept requires(::sus::mem::Copy<T>) { return RangeTo(::sus::move(t)); } constexpr RangeTo end_at(T t) && noexcept { return RangeTo(::sus::move(t)); } constexpr bool operator==(const RangeTo& rhs) const noexcept requires Eq<T> { return finish == rhs.finish; } static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(finish)>; }; template <class T> requires(::sus::ops::Ord<T>) class RangeFull final { public: RangeFull() = default; constexpr bool contains(const T&) const noexcept { return true; } constexpr ::sus::option::Option<const T&> start_bound() const& noexcept { return ::sus::option::Option<const T&>(); } constexpr ::sus::option::Option<const T&> start_bound() && = delete; constexpr ::sus::option::Option<const T&> end_bound() const& noexcept { return ::sus::option::Option<const T&>(); } constexpr ::sus::option::Option<const T&> end_bound() && = delete; constexpr RangeFrom<T> start_at(T t) const& noexcept requires(::sus::mem::Copy<T>) { return RangeFrom<T>(::sus::move(t)); } constexpr RangeFrom<T> start_at(T t) && noexcept { return RangeFrom<T>(::sus::move(t)); } constexpr RangeTo<T> end_at(T t) const& noexcept requires(::sus::mem::Copy<T>) { return RangeTo<T>(::sus::move(t)); } constexpr RangeTo<T> end_at(T t) && noexcept { return RangeTo<T>(::sus::move(t)); } constexpr bool operator==(const RangeFull& rhs) const noexcept requires Eq<T> { return true; } static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<>; static_assert(SusUnsafeTrivialRelocate, "Type is not trivially relocatable"); }; template <class T> constexpr inline Range<T> range(T start, T end) noexcept { return Range<T>(start, end); } template <class T> constexpr inline RangeTo<T> range_to(T t) noexcept { return RangeTo<T>(t); } template <class T> constexpr inline RangeFrom<T> range_from(T t) noexcept { return RangeFrom<T>(t); } } namespace sus::containers { namespace __private { template <class ItemT, ::sus::iter::Iterator<ItemT> I> class GenericSplitN final : public ::sus::iter::IteratorBase<GenericSplitN<ItemT, I>, ItemT> { public: using Item = ItemT; constexpr explicit GenericSplitN(I&& iter, usize count) : iter_(::sus::move(iter)), count_(count) {} constexpr Option<Item> next() noexcept { if (count_ == 0u) return Option<Item>(); else if (count_ == 1u) { count_ -= 1u; return iter_.finish(); } else { count_ -= 1u; return iter_.next(); } } constexpr ::sus::iter::SizeHint size_hint() const noexcept { auto [lower, upper_opt] = iter_.size_hint(); const auto count = count_; return {::sus::ops::min(count, lower), Option<usize>::with( ::sus::move(upper_opt).map_or(count, [count](usize upper) { return ::sus::ops::min(count, upper); }))}; } private: I iter_; usize count_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(iter_), decltype(count_)>; static_assert(SusUnsafeTrivialRelocate, "Type is not trivially relocatable"); }; } template <class ItemT> class [[nodiscard]] Split final : public ::sus::iter::IteratorBase<Split<ItemT>, ::sus::containers::Slice<ItemT>> { public: using Item = ::sus::containers::Slice<ItemT>; constexpr Option<Item> next() noexcept { Option<Item> ret; if (finished_) [[unlikely]] { return ret; } ::sus::num::usize idx; auto it = v_.iter(); while (true) { Option<const ItemT&> o = it.next(); if (o.is_none()) { return finish(); } if (::sus::fn::call_mut(pred_, *o)) { ret = Option<Item>::with(v_[::sus::ops::RangeTo(idx)]); v_ = v_[::sus::ops::RangeFrom(idx + 1u)]; return ret; } idx += 1u; } } constexpr Option<Item> next_back() noexcept { Option<Item> ret; if (finished_) [[unlikely]] { return ret; } ::sus::num::usize idx = v_.len(); auto it = v_.iter().rev(); while (true) { Option<const ItemT&> o = it.next(); if (o.is_none()) { return finish(); } idx -= 1u; if (::sus::fn::call_mut(pred_, *o)) { ret = Option<Item>::with(v_[::sus::ops::RangeFrom(idx + 1u)]); v_ = v_[::sus::ops::RangeTo(idx)]; return ret; } } } constexpr ::sus::iter::SizeHint size_hint() const noexcept { if (v_.is_empty()) { return {0u, ::sus::Option<::sus::num::usize>::with(0u)}; } else { return {1u, ::sus::Option<::sus::num::usize>::with( ::sus::ops::max(1_usize, v_.len()))}; } } private: friend class Slice<ItemT>; friend class Vec<ItemT>; template <class ArrayItemT, size_t N> friend class Array; template <class A, ::sus::iter::Iterator<A> B> friend class __private::GenericSplitN; template <class A> friend class RSplit; constexpr Option<Item> finish() noexcept { if (finished_) { return Option<Item>(); } else { finished_ = true; return Option<Item>::with(v_); } } static constexpr auto with( ::sus::iter::IterRef ref, const Slice<ItemT>& values, ::sus::fn::FnMutRef<bool(const ItemT&)>&& pred) noexcept { return Split(::sus::move(ref), values, ::sus::move(pred)); } constexpr Split(::sus::iter::IterRef ref, const Slice<ItemT>& values, ::sus::fn::FnMutRef<bool(const ItemT&)>&& pred) noexcept : ref_(::sus::move(ref)), v_(values), pred_(::sus::move(pred)) {} [[no_unique_address]] ::sus::iter::IterRef ref_; Slice<ItemT> v_; ::sus::fn::FnMutRef<bool(const ItemT&)> pred_; bool finished_ = false; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(ref_), decltype(v_), decltype(pred_), decltype(finished_)>; static_assert(SusUnsafeTrivialRelocate, "Type is not trivially relocatable"); }; template <class ItemT> class [[nodiscard]] SplitMut final : public ::sus::iter::IteratorBase<SplitMut<ItemT>, ::sus::containers::SliceMut<ItemT>> { public: using Item = ::sus::containers::SliceMut<ItemT>; constexpr Option<Item> next() noexcept { Option<Item> ret; if (finished_) [[unlikely]] { return ret; } ::sus::num::usize idx; auto it = v_.iter(); while (true) { Option<const ItemT&> o = it.next(); if (o.is_none()) { return finish(); } if (::sus::fn::call_mut(pred_, *o)) { ret = Option<Item>::with(v_[::sus::ops::RangeTo(idx)]); v_ = v_[::sus::ops::RangeFrom(idx + 1u)]; return ret; } idx += 1u; } } constexpr Option<Item> next_back() noexcept { Option<Item> ret; if (finished_) [[unlikely]] { return ret; } ::sus::num::usize idx = v_.len(); auto it = v_.iter().rev(); while (true) { Option<const ItemT&> o = it.next(); if (o.is_none()) { return finish(); } idx -= 1u; if (::sus::fn::call_mut(pred_, *o)) { ret = Option<Item>::with(v_[::sus::ops::RangeFrom(idx + 1u)]); v_ = v_[::sus::ops::RangeTo(idx)]; return ret; } } } constexpr ::sus::iter::SizeHint size_hint() const noexcept { if (v_.is_empty()) { return {0u, ::sus::Option<::sus::num::usize>::with(0u)}; } else { return {1u, ::sus::Option<::sus::num::usize>::with( ::sus::ops::max(1_usize, v_.len()))}; } } private: friend class SliceMut<ItemT>; friend class Vec<ItemT>; template <class ArrayItemT, size_t N> friend class Array; template <class A, ::sus::iter::Iterator<A> B> friend class __private::GenericSplitN; template <class A> friend class RSplitMut; constexpr Option<Item> finish() noexcept { if (finished_) { return Option<Item>(); } else { finished_ = true; return Option<Item>::with(v_); } } static constexpr auto with( ::sus::iter::IterRef ref, const SliceMut<ItemT>& values, ::sus::fn::FnMutRef<bool(const ItemT&)>&& pred) noexcept { return SplitMut(::sus::move(ref), values, ::sus::move(pred)); } constexpr SplitMut(::sus::iter::IterRef ref, const SliceMut<ItemT>& values, ::sus::fn::FnMutRef<bool(const ItemT&)>&& pred) noexcept : ref_(::sus::move(ref)), v_(values), pred_(::sus::move(pred)) {} [[no_unique_address]] ::sus::iter::IterRef ref_; SliceMut<ItemT> v_; ::sus::fn::FnMutRef<bool(const ItemT&)> pred_; bool finished_ = false; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(ref_), decltype(v_), decltype(pred_), decltype(finished_)>; static_assert(SusUnsafeTrivialRelocate, "Type is not trivially relocatable"); }; template <class ItemT> class [[nodiscard]] SplitInclusive final : public ::sus::iter::IteratorBase<SplitInclusive<ItemT>, ::sus::containers::Slice<ItemT>> { public: using Item = ::sus::containers::Slice<ItemT>; constexpr Option<Item> next() noexcept { Option<Item> ret; if (finished_) [[unlikely]] { return ret; } ::sus::num::usize idx; const usize last = v_.len() - 1u; auto it = v_.iter(); while (true) { Option<const ItemT&> o = it.next(); if (o.is_none() || ::sus::fn::call_mut(pred_, *o)) { if (idx >= last) { finished_ = true; idx = last; } ret = Option<Item>::with(v_[::sus::ops::RangeTo(idx + 1u)]); v_ = v_[::sus::ops::RangeFrom(idx + 1u)]; return ret; } idx += 1u; } } constexpr Option<Item> next_back() noexcept { Option<Item> ret; if (finished_) [[unlikely]] { return ret; } const auto remainder = v_.is_empty() ? Slice<ItemT>() : v_[::sus::ops::RangeTo(v_.len() - 1u)]; ::sus::num::usize idx = remainder.len(); auto it = remainder.iter().rev(); while (true) { Option<const ItemT&> o = it.next(); if (o.is_none() || ::sus::fn::call_mut(pred_, *o)) { if (idx == 0u) { finished_ = true; } ret = Option<Item>::with(v_[::sus::ops::RangeFrom(idx)]); v_ = v_[::sus::ops::RangeTo(idx)]; return ret; } idx -= 1u; } } constexpr ::sus::iter::SizeHint size_hint() const noexcept { if (v_.is_empty()) { return {0u, ::sus::Option<::sus::num::usize>::with(0u)}; } else { return {1u, ::sus::Option<::sus::num::usize>::with( ::sus::ops::max(1_usize, v_.len()))}; } } private: friend class Slice<ItemT>; friend class Vec<ItemT>; template <class ArrayItemT, size_t N> friend class Array; static constexpr auto with( ::sus::iter::IterRef ref, const Slice<ItemT>& values, ::sus::fn::FnMutRef<bool(const ItemT&)>&& pred) noexcept { return SplitInclusive(::sus::move(ref), values, ::sus::move(pred)); } constexpr SplitInclusive( ::sus::iter::IterRef ref, const Slice<ItemT>& values, ::sus::fn::FnMutRef<bool(const ItemT&)>&& pred) noexcept : ref_(::sus::move(ref)), v_(values), pred_(::sus::move(pred)), finished_(v_.is_empty()) {} [[no_unique_address]] ::sus::iter::IterRef ref_; Slice<ItemT> v_; ::sus::fn::FnMutRef<bool(const ItemT&)> pred_; bool finished_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(ref_), decltype(v_), decltype(pred_), decltype(finished_)>; static_assert(SusUnsafeTrivialRelocate, "Type is not trivially relocatable"); }; template <class ItemT> class [[nodiscard]] SplitInclusiveMut final : public ::sus::iter::IteratorBase<SplitInclusiveMut<ItemT>, ::sus::containers::SliceMut<ItemT>> { public: using Item = ::sus::containers::SliceMut<ItemT>; constexpr Option<Item> next() noexcept { Option<Item> ret; if (finished_) [[unlikely]] { return ret; } ::sus::num::usize idx; const usize last = v_.len() - 1u; auto it = v_.iter(); while (true) { Option<const ItemT&> o = it.next(); if (o.is_none() || ::sus::fn::call_mut(pred_, *o)) { if (idx >= last) { finished_ = true; idx = last; } ret = Option<Item>::with(v_[::sus::ops::RangeTo(idx + 1u)]); v_ = v_[::sus::ops::RangeFrom(idx + 1u)]; return ret; } idx += 1u; } } constexpr Option<Item> next_back() noexcept { Option<Item> ret; if (finished_) [[unlikely]] { return ret; } const auto remainder = v_.is_empty() ? SliceMut<ItemT>() : v_[::sus::ops::RangeTo(v_.len() - 1u)]; ::sus::num::usize idx = remainder.len(); auto it = remainder.iter().rev(); while (true) { Option<const ItemT&> o = it.next(); if (o.is_none() || ::sus::fn::call_mut(pred_, *o)) { if (idx == 0u) { finished_ = true; } ret = Option<Item>::with(v_[::sus::ops::RangeFrom(idx)]); v_ = v_[::sus::ops::RangeTo(idx)]; return ret; } idx -= 1u; } } constexpr ::sus::iter::SizeHint size_hint() const noexcept { if (v_.is_empty()) { return {0u, ::sus::Option<::sus::num::usize>::with(0u)}; } else { return {1u, ::sus::Option<::sus::num::usize>::with( ::sus::ops::max(1_usize, v_.len()))}; } } private: friend class SliceMut<ItemT>; friend class Vec<ItemT>; template <class ArrayItemT, size_t N> friend class Array; static constexpr auto with( ::sus::iter::IterRef ref, const SliceMut<ItemT>& values, ::sus::fn::FnMutRef<bool(const ItemT&)>&& pred) noexcept { return SplitInclusiveMut(::sus::move(ref), values, ::sus::move(pred)); } constexpr SplitInclusiveMut( ::sus::iter::IterRef ref, const SliceMut<ItemT>& values, ::sus::fn::FnMutRef<bool(const ItemT&)>&& pred) noexcept : ref_(::sus::move(ref)), v_(values), pred_(::sus::move(pred)), finished_(v_.is_empty()) {} [[no_unique_address]] ::sus::iter::IterRef ref_; SliceMut<ItemT> v_; ::sus::fn::FnMutRef<bool(const ItemT&)> pred_; bool finished_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(ref_), decltype(v_), decltype(pred_), decltype(finished_)>; static_assert(SusUnsafeTrivialRelocate, "Type is not trivially relocatable"); }; template <class ItemT> class [[nodiscard]] RSplit final : public ::sus::iter::IteratorBase<RSplit<ItemT>, ::sus::containers::Slice<ItemT>> { public: using Item = typename Split<ItemT>::Item; constexpr Option<Item> next() noexcept { return inner_.next_back(); } constexpr Option<Item> next_back() noexcept { return inner_.next(); } constexpr ::sus::iter::SizeHint size_hint() const noexcept { return inner_.size_hint(); } private: friend class Slice<ItemT>; friend class Vec<ItemT>; template <class ArrayItemT, size_t N> friend class Array; template <class A, ::sus::iter::Iterator<A> B> friend class __private::GenericSplitN; constexpr Option<Item> finish() noexcept { return inner_.finish(); } static constexpr auto with(Split<ItemT>&& split) noexcept { return RSplit(::sus::move(split)); } constexpr RSplit(Split<ItemT>&& split) noexcept : inner_(::sus::move(split)) {} Split<ItemT> inner_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(inner_)>; static_assert(SusUnsafeTrivialRelocate, "Type is not trivially relocatable"); }; template <class ItemT> class [[nodiscard]] RSplitMut final : public ::sus::iter::IteratorBase<RSplitMut<ItemT>, ::sus::containers::SliceMut<ItemT>> { public: using Item = typename SplitMut<ItemT>::Item; constexpr Option<Item> next() noexcept { return inner_.next_back(); } constexpr Option<Item> next_back() noexcept { return inner_.next(); } constexpr ::sus::iter::SizeHint size_hint() const noexcept { return inner_.size_hint(); } private: friend class SliceMut<ItemT>; friend class Vec<ItemT>; template <class ArrayItemT, size_t N> friend class Array; template <class A, ::sus::iter::Iterator<A> B> friend class __private::GenericSplitN; Option<Item> finish() noexcept { return inner_.finish(); } static constexpr auto with(SplitMut<ItemT>&& split) noexcept { return RSplitMut(::sus::move(split)); } constexpr RSplitMut(SplitMut<ItemT>&& split) noexcept : inner_(::sus::move(split)) {} SplitMut<ItemT> inner_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(inner_)>; static_assert(SusUnsafeTrivialRelocate, "Type is not trivially relocatable"); }; template <class ItemT> class [[nodiscard]] SplitN final : public ::sus::iter::IteratorBase<SplitN<ItemT>, ::sus::containers::Slice<ItemT>> { public: using Item = typename Split<ItemT>::Item; constexpr Option<Item> next() noexcept { return inner_.next(); } constexpr ::sus::iter::SizeHint size_hint() const noexcept { return inner_.size_hint(); } private: friend class Slice<ItemT>; friend class Vec<ItemT>; template <class ArrayItemT, size_t N> friend class Array; static constexpr auto with(Split<ItemT>&& split, usize n) noexcept { return SplitN(::sus::move(split), n); } constexpr SplitN(Split<ItemT> split, usize n) noexcept : inner_(::sus::move(split), n) {} __private::GenericSplitN<Slice<ItemT>, Split<ItemT>> inner_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(inner_)>; static_assert(SusUnsafeTrivialRelocate, "Type is not trivially relocatable"); }; template <class ItemT> class [[nodiscard]] SplitNMut final : public ::sus::iter::IteratorBase<SplitNMut<ItemT>, ::sus::containers::SliceMut<ItemT>> { public: using Item = typename SplitMut<ItemT>::Item; constexpr Option<Item> next() noexcept { return inner_.next(); } constexpr ::sus::iter::SizeHint size_hint() const noexcept { return inner_.size_hint(); } private: friend class SliceMut<ItemT>; friend class Vec<ItemT>; template <class ArrayItemT, size_t N> friend class Array; static constexpr auto with(SplitMut<ItemT>&& split, usize n) noexcept { return SplitNMut(::sus::move(split), n); } constexpr SplitNMut(SplitMut<ItemT> split, usize n) noexcept : inner_(::sus::move(split), n) {} __private::GenericSplitN<SliceMut<ItemT>, SplitMut<ItemT>> inner_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(inner_)>; static_assert(SusUnsafeTrivialRelocate, "Type is not trivially relocatable"); }; template <class ItemT> class [[nodiscard]] RSplitN final : public ::sus::iter::IteratorBase<RSplitN<ItemT>, ::sus::containers::Slice<ItemT>> { public: using Item = typename RSplit<ItemT>::Item; constexpr Option<Item> next() noexcept { return inner_.next(); } constexpr ::sus::iter::SizeHint size_hint() const noexcept { return inner_.size_hint(); } private: friend class Slice<ItemT>; friend class Vec<ItemT>; template <class ArrayItemT, size_t N> friend class Array; static constexpr auto with(RSplit<ItemT>&& split, usize n) noexcept { return RSplitN(::sus::move(split), n); } constexpr RSplitN(RSplit<ItemT> split, usize n) noexcept : inner_(::sus::move(split), n) {} __private::GenericSplitN<Slice<ItemT>, RSplit<ItemT>> inner_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(inner_)>; static_assert(SusUnsafeTrivialRelocate, "Type is not trivially relocatable"); }; template <class ItemT> class [[nodiscard]] RSplitNMut final : public ::sus::iter::IteratorBase<RSplitNMut<ItemT>, ::sus::containers::SliceMut<ItemT>> { public: using Item = typename RSplitMut<ItemT>::Item; constexpr Option<Item> next() noexcept { return inner_.next(); } constexpr ::sus::iter::SizeHint size_hint() const noexcept { return inner_.size_hint(); } private: friend class SliceMut<ItemT>; friend class Vec<ItemT>; template <class ArrayItemT, size_t N> friend class Array; static constexpr auto with(RSplitMut<ItemT>&& split, usize n) noexcept { return RSplitNMut(::sus::move(split), n); } constexpr RSplitNMut(RSplitMut<ItemT> split, usize n) noexcept : inner_(::sus::move(split), n) {} __private::GenericSplitN<SliceMut<ItemT>, RSplitMut<ItemT>> inner_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(inner_)>; static_assert(SusUnsafeTrivialRelocate, "Type is not trivially relocatable"); }; } namespace sus::containers { template <class ItemT> class [[nodiscard]] Windows final : public ::sus::iter::IteratorBase<Windows<ItemT>, ::sus::containers::Slice<ItemT>> { public: using Item = ::sus::containers::Slice<ItemT>; constexpr Option<Item> next() noexcept { Option<Item> ret; if (size_ > v_.len()) { return ret; } else { ret = Option<Item>::with(v_[::sus::ops::RangeTo<usize>(size_)]); v_ = v_[::sus::ops::RangeFrom<usize>(1u)]; return ret; } } constexpr Option<Item> next_back() noexcept { Option<Item> ret; if (size_ > v_.len()) { return ret; } else { ret = Option<Item>::with( v_[::sus::ops::RangeFrom<usize>(v_.len() - size_)]); v_ = v_[::sus::ops::RangeTo<usize>(v_.len() - 1u)]; return ret; } } constexpr ::sus::iter::SizeHint size_hint() const noexcept { const auto remaining = exact_size_hint(); return {remaining, ::sus::Option<::sus::num::usize>::with(remaining)}; } constexpr ::sus::num::usize exact_size_hint() const noexcept { if (size_ > v_.len()) { return 0u; } else { return v_.len() - size_ + 1u; } } private: friend class Slice<ItemT>; friend class Vec<ItemT>; template <class ArrayItemT, size_t N> friend class Array; static constexpr auto with(::sus::iter::IterRef ref, const Slice<ItemT>& values, usize size) noexcept { return Windows(::sus::move(ref), values, size); } constexpr Windows(::sus::iter::IterRef ref, const Slice<ItemT>& values, usize size) noexcept : ref_(::sus::move(ref)), v_(values), size_(size) {} [[no_unique_address]] ::sus::iter::IterRef ref_; Slice<ItemT> v_; usize size_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(ref_), decltype(v_), decltype(size_)>; static_assert(SusUnsafeTrivialRelocate, "Type is not trivially relocatable"); }; template <class ItemT> class [[nodiscard]] WindowsMut final : public ::sus::iter::IteratorBase<WindowsMut<ItemT>, ::sus::containers::SliceMut<ItemT>> { public: using Item = ::sus::containers::SliceMut<ItemT>; WindowsMut(WindowsMut&&) = default; WindowsMut& operator=(WindowsMut&&) = default; WindowsMut clone() const noexcept { return WindowsMut(::sus::clone(v_), ::sus::clone(size_)); } Option<Item> next() noexcept { Option<Item> ret; if (size_ > v_.len()) { return ret; } else { ret = Option<Item>::with(v_[::sus::ops::RangeTo<usize>(size_)]); v_ = v_[::sus::ops::RangeFrom<usize>(1u)]; return ret; } } Option<Item> next_back() noexcept { Option<Item> ret; if (size_ > v_.len()) { return ret; } else { ret = Option<Item>::with( v_[::sus::ops::RangeFrom<usize>(v_.len() - size_)]); v_ = v_[::sus::ops::RangeTo<usize>(v_.len() - 1u)]; return ret; } } ::sus::iter::SizeHint size_hint() const noexcept { const auto remaining = exact_size_hint(); return {remaining, ::sus::Option<::sus::num::usize>::with(remaining)}; } ::sus::num::usize exact_size_hint() const noexcept { if (size_ > v_.len()) { return 0u; } else { return v_.len() - size_ + 1u; } } private: friend class SliceMut<ItemT>; friend class Vec<ItemT>; template <class ArrayItemT, size_t N> friend class Array; static constexpr auto with(::sus::iter::IterRef ref, const SliceMut<ItemT>& values, usize size) noexcept { return WindowsMut(::sus::move(ref), values, size); } constexpr WindowsMut(::sus::iter::IterRef ref, const SliceMut<ItemT>& values, usize size) noexcept : ref_(::sus::move(ref)), v_(values), size_(size) {} [[no_unique_address]] ::sus::iter::IterRef ref_; SliceMut<ItemT> v_; usize size_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(ref_), decltype(v_), decltype(size_)>; static_assert(SusUnsafeTrivialRelocate, "Type is not trivially relocatable"); }; } namespace sus::containers { template <class T, class Sep> concept Join = requires(const T& t, const ::sus::num::usize& cap) { requires ::sus::mem::Clone<Sep>; { t.len() } -> std::same_as<::sus::num::usize>; typename T::JoinOutputType; { T::JoinOutputType::with_capacity(cap) } -> std::same_as<typename T::JoinOutputType>; requires requires(typename T::JoinOutputType& container, const Sep& sep) { { t.join_into(container) } -> std::same_as<void>; { T::join_sep_into(container, sep) } -> std::same_as<void>; }; }; } namespace sus::construct { template <class To, class From> struct TransmogrifyImpl; template <::sus::mem::Copy T> struct TransmogrifyImpl<T, T> { constexpr static T mog_from(const T& from) noexcept { return from; } }; template <class To, class From> concept Transmogrify = requires(const From& from) { { ::sus::construct::TransmogrifyImpl<To, From>::mog_from(from) } noexcept -> std::same_as<To>; }; template <class To, class From> requires(Transmogrify<To, From>) constexpr inline To mog(const From& from) { return TransmogrifyImpl<To, From>::mog_from(from); } } namespace sus { using ::sus::construct::mog; } template <sus::num::Integer T, sus::num::Integer F> struct sus::construct::TransmogrifyImpl<T, F> { constexpr static T mog_from(const F& from) noexcept { return T(::sus::mog<decltype(std::declval<T>().primitive_value)>( from.primitive_value)); } }; template <sus::num::Integer T, sus::num::PrimitiveInteger F> struct sus::construct::TransmogrifyImpl<T, F> { constexpr static T mog_from(const F& from) noexcept { return T(::sus::mog<decltype(std::declval<T>().primitive_value)>(from)); } }; template <sus::num::Integer T, sus::num::PrimitiveEnum F> struct sus::construct::TransmogrifyImpl<T, F> { constexpr static T mog_from(const F& from) noexcept { return T(::sus::mog<decltype(std::declval<T>().primitive_value)>( static_cast<std::underlying_type_t<F>>(from))); } }; template <sus::num::Integer T, sus::num::PrimitiveEnumClass F> struct sus::construct::TransmogrifyImpl<T, F> { constexpr static T mog_from(const F& from) noexcept { return T(::sus::mog<decltype(std::declval<T>().primitive_value)>( static_cast<std::underlying_type_t<F>>(from))); } }; template <sus::num::Integer T, sus::num::Float F> struct sus::construct::TransmogrifyImpl<T, F> { constexpr static T mog_from(const F& from) noexcept { return T(::sus::mog<decltype(std::declval<T>().primitive_value)>( from.primitive_value)); } }; template <sus::num::Integer T, sus::num::PrimitiveFloat F> struct sus::construct::TransmogrifyImpl<T, F> { constexpr static T mog_from(const F& from) noexcept { return T(::sus::mog<decltype(std::declval<T>().primitive_value)>(from)); } }; template <sus::num::PrimitiveInteger T, sus::num::Integer F> struct sus::construct::TransmogrifyImpl<T, F> { constexpr static T mog_from(const F& from) noexcept { return ::sus::mog<T>(from.primitive_value); } }; template <sus::num::PrimitiveInteger T, sus::num::PrimitiveInteger F> struct sus::construct::TransmogrifyImpl<T, F> { constexpr static T mog_from(const F& from) noexcept { return static_cast<T>(from); } }; template <sus::num::PrimitiveInteger T, sus::num::PrimitiveEnum F> struct sus::construct::TransmogrifyImpl<T, F> { constexpr static T mog_from(const F& from) noexcept { return static_cast<T>(static_cast<std::underlying_type_t<F>>(from)); } }; template <sus::num::PrimitiveInteger T, sus::num::PrimitiveEnumClass F> struct sus::construct::TransmogrifyImpl<T, F> { constexpr static T mog_from(const F& from) noexcept { return static_cast<T>(static_cast<std::underlying_type_t<F>>(from)); } }; template <sus::num::PrimitiveInteger T, sus::num::Float F> struct sus::construct::TransmogrifyImpl<T, F> { constexpr static T mog_from(const F& from) noexcept { if (from.is_nan()) [[unlikely]] return T(0); struct MinMax { F min, max; }; constexpr MinMax minmax = []() { if constexpr (::sus::mem::size_of<T>() == 1u) { if constexpr (std::is_signed_v<T>) { if constexpr (::sus::mem::size_of<F>() == 4u) { return MinMax(-128.f, 127.f); } else { return MinMax(-128.0, 127.0); } } else { if constexpr (::sus::mem::size_of<F>() == 4u) { return MinMax(0.f, 255.f); } else { return MinMax(0.0, 255.0); } } } else if constexpr (::sus::mem::size_of<T>() == 2u) { if constexpr (std::is_signed_v<T>) { if constexpr (::sus::mem::size_of<F>() == 4u) { return MinMax(-32768.f, 32767.f); } else { return MinMax(-32768.0, 32767.0); } } else { if constexpr (::sus::mem::size_of<F>() == 4u) { return MinMax(0.f, 65535.f); } else { return MinMax(0.0, 65535.0); } } } else if constexpr (::sus::mem::size_of<T>() == 4u) { if constexpr (std::is_signed_v<T>) { if constexpr (::sus::mem::size_of<F>() == 4u) { return MinMax(-2147483648.f, 2147483647.f); } else { return MinMax(-2147483648.0, 2147483647.0); } } else { if constexpr (::sus::mem::size_of<F>() == 4u) { return MinMax(0.f, 4294967295.f); } else { return MinMax(0.0, 4294967295.0); } } } else { static_assert(::sus::mem::size_of<T>() == 8u); if constexpr (std::is_signed_v<T>) { if constexpr (::sus::mem::size_of<F>() == 4u) { return MinMax(-9223372036854775808.f, 9223372036854775807.f); } else { return MinMax(-9223372036854775808.0, 9223372036854775807.0); } } else { if constexpr (::sus::mem::size_of<F>() == 4u) { return MinMax(0.f, 18446744073709551615.f); } else { return MinMax(0.0, 18446744073709551615.0); } } } }(); if (from >= minmax.max) [[unlikely]] return ::sus::num::__private::max_value<T>(); if (from <= minmax.min) [[unlikely]] return ::sus::num::__private::min_value<T>(); return static_cast<T>(from.primitive_value); } }; template <sus::num::PrimitiveInteger T, sus::num::PrimitiveFloat F> struct sus::construct::TransmogrifyImpl<T, F> { constexpr static T mog_from(const F& from) noexcept { if constexpr (::sus::mem::size_of<F>() == 4u) { return ::sus::mog<T>(::sus::num::f32(from)); } else { static_assert(::sus::mem::size_of<F>() == 8u); return ::sus::mog<T>(::sus::num::f64(from)); } } }; template <sus::num::PrimitiveEnum T, sus::num::Integer F> struct sus::construct::TransmogrifyImpl<T, F> { constexpr static T mog_from(const F& from) noexcept { return static_cast<T>(::sus::mog<std::underlying_type_t<T>>(from)); } }; template <sus::num::PrimitiveEnum T, sus::num::PrimitiveInteger F> struct sus::construct::TransmogrifyImpl<T, F> { constexpr static T mog_from(const F& from) noexcept { return static_cast<T>(::sus::mog<std::underlying_type_t<T>>(from)); } }; template <sus::num::PrimitiveEnum T, sus::num::PrimitiveEnum F> struct sus::construct::TransmogrifyImpl<T, F> { constexpr static T mog_from(const F& from) noexcept { return static_cast<T>(::sus::mog<std::underlying_type_t<T>>( static_cast<std::underlying_type_t<F>>(from))); } }; template <sus::num::PrimitiveEnum T, sus::num::PrimitiveEnumClass F> struct sus::construct::TransmogrifyImpl<T, F> { constexpr static T mog_from(const F& from) noexcept { return static_cast<T>(::sus::mog<std::underlying_type_t<T>>( static_cast<std::underlying_type_t<F>>(from))); } }; template <sus::num::PrimitiveEnumClass T, sus::num::Integer F> struct sus::construct::TransmogrifyImpl<T, F> { constexpr static T mog_from(const F& from) noexcept { return static_cast<T>(::sus::mog<std::underlying_type_t<T>>(from)); } }; template <sus::num::PrimitiveEnumClass T, sus::num::PrimitiveInteger F> struct sus::construct::TransmogrifyImpl<T, F> { constexpr static T mog_from(const F& from) noexcept { return static_cast<T>(::sus::mog<std::underlying_type_t<T>>(from)); } }; template <sus::num::PrimitiveEnumClass T, sus::num::PrimitiveEnum F> struct sus::construct::TransmogrifyImpl<T, F> { constexpr static T mog_from(const F& from) noexcept { return static_cast<T>(::sus::mog<std::underlying_type_t<T>>( static_cast<std::underlying_type_t<F>>(from))); } }; template <sus::num::PrimitiveEnumClass T, sus::num::PrimitiveEnumClass F> struct sus::construct::TransmogrifyImpl<T, F> { constexpr static T mog_from(const F& from) noexcept { return static_cast<T>(::sus::mog<std::underlying_type_t<T>>( static_cast<std::underlying_type_t<F>>(from))); } }; template <sus::num::Float T, sus::num::Integer F> struct sus::construct::TransmogrifyImpl<T, F> { constexpr static T mog_from(const F& from) noexcept { return T(::sus::mog<decltype(std::declval<T>().primitive_value)>( from.primitive_value)); } }; template <sus::num::Float T, sus::num::PrimitiveInteger F> struct sus::construct::TransmogrifyImpl<T, F> { constexpr static T mog_from(const F& from) noexcept { return T(::sus::mog<decltype(std::declval<T>().primitive_value)>(from)); } }; template <sus::num::Float T, sus::num::Float F> struct sus::construct::TransmogrifyImpl<T, F> { constexpr static T mog_from(const F& from) noexcept { return T(::sus::mog<decltype(std::declval<T>().primitive_value)>( from.primitive_value)); } }; template <sus::num::Float T, sus::num::PrimitiveFloat F> struct sus::construct::TransmogrifyImpl<T, F> { constexpr static T mog_from(const F& from) noexcept { return T(::sus::mog<decltype(std::declval<T>().primitive_value)>(from)); } }; template <sus::num::PrimitiveFloat T, sus::num::Integer F> struct sus::construct::TransmogrifyImpl<T, F> { constexpr static T mog_from(const F& from) noexcept { return ::sus::mog<T>(from.primitive_value); } }; template <sus::num::PrimitiveFloat T, sus::num::PrimitiveInteger F> struct sus::construct::TransmogrifyImpl<T, F> { constexpr static T mog_from(const F& from) noexcept { return ::sus::num::__private::static_cast_int_to_float<float>(from); } }; template <sus::num::PrimitiveFloat T, sus::num::Float F> struct sus::construct::TransmogrifyImpl<T, F> { constexpr static T mog_from(const F& from) noexcept { return ::sus::mog<T>(from.primitive_value); } }; template <sus::num::PrimitiveFloat T, sus::num::PrimitiveFloat F> struct sus::construct::TransmogrifyImpl<T, F> { constexpr static T mog_from(const F& from) noexcept { static_assert(::sus::mem::size_of<T>() == 4u || ::sus::mem::size_of<T>() == 8u); static_assert(::sus::mem::size_of<F>() == 4u || ::sus::mem::size_of<F>() == 8u); if constexpr (::sus::mem::size_of<T>() == 4u) { if constexpr (::sus::mem::size_of<F>() == 4u) { return from; } else { return ::sus::num::__private::static_cast_to_smaller_float<float>(from); } } else { if constexpr (::sus::mem::size_of<F>() == 4u) { return T{from}; } else { return from; } } } }; namespace sus::ptr { template <class T> requires(sus::mem::Move<T> && !std::is_const_v<T>) inline constexpr void swap_nonoverlapping(::sus::marker::UnsafeFnMarker, T* x, T* y, usize count) noexcept { ::sus::check(x != nullptr); ::sus::check(y != nullptr); if (!std::is_constant_evaluated()) { ::sus::check(reinterpret_cast<uintptr_t>(x) % alignof(T) == 0); ::sus::check(reinterpret_cast<uintptr_t>(y) % alignof(T) == 0); } ::sus::check((x <= y && x <= y - count.primitive_value) || (y <= x && y <= x - count.primitive_value)); constexpr usize t_size = ::sus::mem::size_of<T>(); constexpr bool has_split_up_alignment = alignof(T) <= alignof(uintptr_t); constexpr bool has_split_up_size = !t_size.is_power_of_two() || t_size > ::sus::mem::size_of<uintptr_t>() * 2; const ::sus::Option<usize> opt_byte_count = count.checked_mul(t_size); if (std::is_constant_evaluated() || !::sus::mem::relocate_by_memcpy<T> || !has_split_up_alignment || !has_split_up_size || opt_byte_count.is_none()) { for (usize i; i < count; i += 1u) { ::sus::mem::swap_nonoverlapping(::sus::marker::unsafe_fn, *(x + i), *(y + i)); } return; } const usize byte_count = *opt_byte_count; if constexpr (alignof(T) == alignof(uintptr_t) && t_size % ::sus::mem::size_of<uintptr_t>() == 0u) { char* const cx = reinterpret_cast<char*>(x); char* const cy = reinterpret_cast<char*>(y); alignas(alignof(uintptr_t)) char buf[::sus::mem::size_of<uintptr_t>()]; for (usize i; i < byte_count; i += ::sus::mem::size_of<uintptr_t>()) { ::sus::ptr::copy_nonoverlapping(::sus::marker::unsafe_fn, cx + i, buf, ::sus::mem::size_of<uintptr_t>()); ::sus::ptr::copy_nonoverlapping(::sus::marker::unsafe_fn, cy + i, cx + i, ::sus::mem::size_of<uintptr_t>()); ::sus::ptr::copy_nonoverlapping(::sus::marker::unsafe_fn, buf, cy + i, ::sus::mem::size_of<uintptr_t>()); } } else { char* const cx = reinterpret_cast<char*>(x); char* const cy = reinterpret_cast<char*>(y); ::sus::check((cx <= cy && cx <= cy - byte_count.primitive_value) || (cy <= cx && cy <= cx - byte_count.primitive_value)); char buf; for (usize i; i < byte_count; i += 1u) { buf = *(cx + i); *(cx + i) = *(cy + i); *(cy + i) = buf; } } } } namespace sus::containers { template <class T> class Slice final { public: static_assert(!std::is_reference_v<T>, "Slice holds references, so the type parameter can not also be " "a reference"); static_assert(!std::is_const_v<T>, "Slice inner type should not be const, it provides const " "access to the slice regardless."); constexpr Slice() : Slice(::sus::iter::IterRefCounter::empty_for_view(), nullptr, 0_usize) { } __attribute__((pure)) static constexpr inline Slice from_raw_parts( ::sus::marker::UnsafeFnMarker, ::sus::iter::IterRefCounter refs, const T* data, usize len) noexcept { ::sus::check(len <= ::sus::mog<usize>(isize::MAX)); return Slice(::sus::move(refs), const_cast<T*>(data), len); } template <size_t N> requires(N <= ::sus::mog<usize>(isize::MAX)) __attribute__((pure)) static constexpr inline Slice from( const T (&data)[N]) { return Slice(sus::iter::IterRefCounter::empty_for_view(), const_cast<T*>(data), N); } __attribute__((pure)) constexpr SliceIter<const T&> into_iter() && noexcept { return SliceIter<const T&>::with( iter_refs_.to_iter_from_view(), data_, len_); } template <class U> requires(::sus::ops::Eq<T, U>) friend constexpr inline bool operator==(const Slice<T>& l, const Slice<U>& r) noexcept { if (l.len() != r.len()) return false; const T* lp = l.data_; const U* rp = r.data_; const T* const endp = lp + l.len(); while (lp != endp) { if (!(*lp == *rp)) return false; lp += 1u; rp += 1u; } return true; } template <class U> requires(!::sus::ops::Eq<T, U>) friend constexpr inline bool operator==(const Slice<T>& l, const Slice<U>& r) = delete; __attribute__((pure)) constexpr inline const T& operator[](usize i) const& noexcept { ::sus::check(i < len()); return *(as_ptr() + i); } __attribute__((pure)) constexpr inline Slice<T> operator[]( const ::sus::ops::RangeBounds<usize> auto range) const& noexcept { const usize length = len(); const usize rstart = range.start_bound().unwrap_or(0u); const usize rend = range.end_bound().unwrap_or(length); const usize rlen = rend >= rstart ? rend - rstart : 0u; ::sus::check(rlen <= length); ::sus::check(rstart <= length && rstart <= length - rlen); return Slice<T>::from_raw_parts(::sus::marker::unsafe_fn, iter_refs_.to_view_from_view(), as_ptr() + rstart, rlen); } void drop_iterator_invalidation_tracking(::sus::marker::UnsafeFnMarker) { iter_refs_ = ::sus::iter::IterRefCounter::empty_for_view(); } __attribute__((pure)) constexpr inline bool is_empty() const& noexcept { return len() == 0u; } __attribute__((pure)) constexpr inline ::sus::num::usize len() const& noexcept { return len_; } __attribute__((pure)) constexpr inline const T* as_ptr() const& noexcept { return data_; } __attribute__((pure)) constexpr ::sus::ops::Range<const T*> as_ptr_range() const& noexcept { return ::sus::ops::Range<const T*>(as_ptr(), as_ptr() + len()); } constexpr ::sus::result::Result<::sus::num::usize, ::sus::num::usize> binary_search(const T& x) const& noexcept requires(::sus::ops::Ord<T>) { return binary_search_by( [&x](const T& p) -> std::strong_ordering { return p <=> x; }); } constexpr ::sus::result::Result<::sus::num::usize, ::sus::num::usize> binary_search_by( ::sus::fn::FnMutRef<std::strong_ordering(const T&)> f) const& noexcept requires(::sus::ops::Ord<T>) { using Result = ::sus::result::Result<::sus::num::usize, ::sus::num::usize>; ::sus::num::usize size = len(); ::sus::num::usize left = 0u; ::sus::num::usize right = size; while (left < right) { auto mid = left + size / 2u; auto cmp = ::sus::fn::call_mut(f, get_unchecked(::sus::marker::unsafe_fn, mid)); if (cmp == std::strong_ordering::less) { left = mid + 1u; } else if (cmp == std::strong_ordering::greater) { right = mid; } else { static_assert(std::same_as<std::decay_t<decltype(::sus::marker::unsafe_fn)>, ::sus::marker::UnsafeFnMarker>); #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wassume" __builtin_assume(mid.primitive_value < len_.primitive_value) #pragma clang diagnostic pop ; return Result::with(mid); } size = right - left; } static_assert(std::same_as<std::decay_t<decltype(::sus::marker::unsafe_fn)>, ::sus::marker::UnsafeFnMarker>); #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wassume" __builtin_assume(left.primitive_value <= len_.primitive_value) #pragma clang diagnostic pop ; return Result::with_err(left); } template <::sus::ops::Ord Key> ::sus::result:: Result<::sus::num::usize, ::sus::num::usize> constexpr binary_search_by_key( const Key& key, ::sus::fn::FnMut<Key(const T&)> auto&& f) const& noexcept { return binary_search_by([&key, &f](const T& p) -> std::strong_ordering { return ::sus::fn::call_mut(f, p) <=> key; }); } constexpr Chunks<T> chunks(::sus::num::usize chunk_size) const& noexcept { return Chunks<T>::with(iter_refs_.to_iter_from_view(), *this, chunk_size); } constexpr ChunksExact<T> chunks_exact( ::sus::num::usize chunk_size) const& noexcept { return ChunksExact<T>::with(iter_refs_.to_iter_from_view(), *this, chunk_size); } using ConcatOutputType = ::sus::containers::Vec<T>; constexpr auto concat() const& noexcept requires(::sus::containers::Concat<T>) { const auto length = len(); ::sus::num::usize cap; for (::sus::num::usize i; i < length; i += 1u) { cap += get_unchecked(::sus::marker::unsafe_fn, i).len(); } using Container = typename T::ConcatOutputType; auto out = Container::with_capacity(cap); for (::sus::num::usize i; i < length; i += 1u) { get_unchecked(::sus::marker::unsafe_fn, i).concat_into(out); } return out; } constexpr void concat_into(::sus::containers::Vec<T>& vec) const& noexcept requires(::sus::mem::Clone<T>) { vec.extend_from_slice(*this); } constexpr bool contains(const T& x) const& noexcept requires(::sus::ops::Eq<T>) { const auto length = len(); const auto* const p = as_ptr(); for (::sus::num::usize i; i < length; i += 1u) { if (*(p + i) == x) return true; } return false; } constexpr bool ends_with(const Slice<T>& suffix) const& noexcept requires(::sus::ops::Eq<T>) { const auto m = len(); const auto n = suffix.len(); return m >= n && suffix == (*this)[::sus::ops::RangeFrom(m - n)]; } __attribute__((pure)) constexpr ::sus::Option<const T&> first() const& noexcept { if (len() > 0u) { return ::sus::Option<const T&>::with( get_unchecked(::sus::marker::unsafe_fn, 0u)); } else { return ::sus::Option<const T&>(); } } __attribute__((pure)) constexpr Option<const T&> get(::sus::num::usize i) const& noexcept { if (i < len()) [[likely]] return Option<const T&>::with(get_unchecked(::sus::marker::unsafe_fn, i)); else return Option<const T&>(); } __attribute__((pure)) constexpr inline const T& get_unchecked( ::sus::marker::UnsafeFnMarker, ::sus::num::usize i) const& noexcept { ::sus::check(i.primitive_value < len_.primitive_value); return as_ptr()[size_t{i}]; } __attribute__((pure)) constexpr Option<Slice<T>> get_range( const ::sus::ops::RangeBounds<::sus::num::usize> auto range) const& noexcept { const ::sus::num::usize length = len(); const ::sus::num::usize rstart = range.start_bound().unwrap_or(0u); const ::sus::num::usize rend = range.end_bound().unwrap_or(length); const ::sus::num::usize rlen = rend >= rstart ? rend - rstart : 0u; if (rlen > length) return sus::none(); if (rstart > length || rstart > length - rlen) return sus::none(); return Option<Slice<T>>::with(Slice<T>::from_raw_parts( ::sus::marker::unsafe_fn, iter_refs_.to_view_from_view(), as_ptr() + rstart, rlen)); } __attribute__((pure)) constexpr Slice<T> get_range_unchecked( ::sus::marker::UnsafeFnMarker, const ::sus::ops::RangeBounds<::sus::num::usize> auto range) const& noexcept { const ::sus::num::usize rstart = range.start_bound().unwrap_or(0u); const ::sus::num::usize rend = range.end_bound().unwrap_or(len()); const ::sus::num::usize rlen = rend >= rstart ? rend - rstart : 0u; return Slice<T>::from_raw_parts( ::sus::marker::unsafe_fn, iter_refs_.to_view_from_view(), as_ptr() + rstart, rlen); } __attribute__((pure)) constexpr SliceIter<const T&> iter() const& noexcept { return SliceIter<const T&>::with(iter_refs_.to_iter_from_view(), as_ptr(), len()); } using JoinOutputType = ::sus::containers::Vec<T>; template <class Sep> constexpr auto join(const Sep& separator) const& noexcept requires(::sus::containers::Join<T, Sep>) { const auto length = len(); ::sus::num::usize cap; for (::sus::num::usize i; i < length; i += 1u) { cap += get_unchecked(::sus::marker::unsafe_fn, i).len(); } using Container = typename T::JoinOutputType; auto out = Container::with_capacity(cap); if (length > 0u) get_unchecked(::sus::marker::unsafe_fn, 0u).join_into(out); for (::sus::num::usize i = 1u; i < length; i += 1u) { T::join_sep_into(out, separator); get_unchecked(::sus::marker::unsafe_fn, i).join_into(out); } return out; } constexpr void join_into(::sus::containers::Vec<T>& vec) const& noexcept requires(::sus::mem::Clone<T>) { vec.extend_from_slice(*this); } static constexpr void join_sep_into(::sus::containers::Vec<T>& vec, const Slice<T>& separator) noexcept requires(::sus::mem::Clone<T>) { vec.extend_from_slice(separator); } static constexpr void join_sep_into(::sus::containers::Vec<T>& vec, const T& separator) noexcept requires(::sus::mem::Clone<T>) { vec.push(::sus::clone(separator)); } __attribute__((pure)) constexpr ::sus::Option<const T&> last() const& noexcept { const auto length = len(); if (length > 0u) return ::sus::Option<const T&>::with(*(as_ptr() + length - 1u)); else return ::sus::Option<const T&>(); } constexpr ::sus::num::usize partition_point( ::sus::fn::FnMutRef<bool(const T&)> pred) const& noexcept { return binary_search_by([pred = ::sus::move(pred)](const T& x) { if (::sus::fn::call_mut(pred, x)) { return std::strong_ordering::less; } else { return std::strong_ordering::greater; } }) .unwrap_or_else([](::sus::num::usize i) { return i; }); } constexpr RChunks<T> rchunks(::sus::num::usize chunk_size) const& noexcept { return RChunks<T>::with(iter_refs_.to_iter_from_view(), *this, chunk_size); } constexpr RChunksExact<T> rchunks_exact( ::sus::num::usize chunk_size) const& noexcept { return RChunksExact<T>::with(iter_refs_.to_iter_from_view(), *this, chunk_size); } constexpr ::sus::containers::Vec<T> repeat(usize n) const& noexcept requires(::sus::mem::TrivialCopy<T>) { auto buf = ::sus::containers::Vec<T>(); if (n == 0u) return buf; const usize l = len(); const usize capacity = l.saturating_mul(n); buf.reserve(capacity); buf.extend(iter()); { usize m = n >> 1u; while (m > 0u) { ::sus::ptr::copy_nonoverlapping(::sus::marker::unsafe_fn, buf.as_ptr(), buf.as_mut_ptr() + buf.len(), buf.len()); const usize buf_len = buf.len(); buf.set_len(::sus::marker::unsafe_fn, buf_len * 2u); m >>= 1u; } } const usize rem_len = capacity - buf.len(); if (rem_len > 0u) { ::sus::ptr::copy_nonoverlapping(::sus::marker::unsafe_fn, buf.as_ptr(), buf.as_mut_ptr() + buf.len(), rem_len); buf.set_len(::sus::marker::unsafe_fn, capacity); } return buf; } constexpr RSplit<T> rsplit( ::sus::fn::FnMutRef<bool(const T&)> pred) const& noexcept { return RSplit<T>::with( Split<T>::with(iter_refs_.to_iter_from_view(), *this, ::sus::move(pred))); } constexpr RSplitN<T> rsplitn( usize n, ::sus::fn::FnMutRef<bool(const T&)> pred) const& noexcept { return RSplitN<T>::with(RSplit<T>::with(Split<T>::with(iter_refs_.to_iter_from_view(), *this, ::sus::move(pred))), n); } constexpr Split<T> split( ::sus::fn::FnMutRef<bool(const T&)> pred) const& noexcept { return Split<T>::with(iter_refs_.to_iter_from_view(), *this, ::sus::move(pred)); } __attribute__((pure)) constexpr ::sus::Tuple<Slice<T>, Slice<T>> split_at( ::sus::num::usize mid) const& noexcept { ::sus::check(mid <= len()); return split_at_unchecked(::sus::marker::unsafe_fn, mid); } __attribute__((pure)) constexpr ::sus::Tuple<Slice<T>, Slice<T>> split_at_unchecked( ::sus::marker::UnsafeFnMarker, ::sus::num::usize mid) const& noexcept { ::sus::check(mid.primitive_value <= len_.primitive_value); const ::sus::num::usize rem = len().unchecked_sub(::sus::marker::unsafe_fn, mid); return ::sus::Tuple<Slice<T>, Slice<T>>::with( Slice<T>::from_raw_parts(::sus::marker::unsafe_fn, iter_refs_.to_view_from_view(), as_ptr(), mid), Slice<T>::from_raw_parts(::sus::marker::unsafe_fn, iter_refs_.to_view_from_view(), as_ptr() + mid, rem)); } __attribute__((pure)) constexpr ::sus::Option<::sus::Tuple<const T&, Slice<T>>> split_first() const& noexcept { if (is_empty()) return ::sus::none(); return ::sus::some( ::sus::tuple(*as_ptr(), (*this)[::sus::ops::RangeFrom<usize>(1u)])); } constexpr SplitInclusive<T> split_inclusive( ::sus::fn::FnMutRef<bool(const T&)> pred) const& noexcept { return SplitInclusive<T>::with(iter_refs_.to_iter_from_view(), *this, ::sus::move(pred)); } __attribute__((pure)) constexpr ::sus::Option<::sus::Tuple<const T&, Slice<T>>> split_last() const& noexcept { if (is_empty()) return ::sus::none(); const usize last = len() - 1u; return ::sus::some(::sus::tuple(*(as_ptr() + last), (*this)[::sus::ops::RangeTo<usize>(last)])); } constexpr SplitN<T> splitn( usize n, ::sus::fn::FnMutRef<bool(const T&)> pred) const& noexcept { return SplitN<T>::with( Split<T>::with(iter_refs_.to_iter_from_view(), *this, ::sus::move(pred)), n); } constexpr bool starts_with(const Slice<T>& needle) const& requires(::sus::ops::Eq<T>) { const auto n = needle.len(); return len() >= n && needle == (*this)[::sus::ops::RangeTo(n)]; } constexpr ::sus::Option<Slice<T>> strip_prefix( const Slice<T>& prefix) const& noexcept requires(::sus::ops::Eq<T>) { const usize n = prefix.len(); if (n <= len()) { auto [head, tail] = split_at(n); if (head == prefix) { return ::sus::Option<Slice<T>>::with(tail); } } return ::sus::Option<Slice<T>>(); } constexpr ::sus::Option<Slice<T>> strip_suffix( const Slice<T>& suffix) const& noexcept requires(::sus::ops::Eq<T>) { const auto l = len(); const auto n = suffix.len(); if (n <= l) { auto [head, tail] = split_at(l - n); if (tail == suffix) { return ::sus::Option<Slice<T>>::with(head); } } return ::sus::Option<Slice<T>>(); } Vec<T> to_vec() const& noexcept requires(::sus::mem::Clone<T>); __attribute__((pure)) constexpr Windows<T> windows(usize size) const& noexcept { ::sus::check(size > 0u); return Windows<T>::with(iter_refs_.to_iter_from_view(), *this, size); } private: constexpr Slice(::sus::iter::IterRefCounter refs, T* data, usize len) noexcept : iter_refs_(::sus::move(refs)), data_(data), len_(len) {} friend class SliceMut<T>; template <class VecT> friend class Vec; [[no_unique_address]] ::sus::iter::IterRefCounter iter_refs_; T* data_; usize len_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(data_), decltype(len_)>; static_assert(SusUnsafeTrivialRelocate, "Type is not trivially relocatable"); }; template <class T> Vec<T> Slice<T>::to_vec() const& noexcept requires(::sus::mem::Clone<T>) { auto v = Vec<T>::with_capacity(len_); for (::sus::usize i; i < len_; i += 1u) { v.push(::sus::clone(*(data_ + i))); } return v; } template <class T> class SliceMut final { public: static_assert( !std::is_reference_v<T>, "SliceMut holds references, so the type parameter can not also be " "a reference"); static_assert(!std::is_const_v<T>, "SliceMut inner type should not be const, it provides mutable " "access to the slice. Use Slice to represent const access."); constexpr SliceMut() = default; __attribute__((pure)) static constexpr inline SliceMut from_raw_parts_mut( ::sus::marker::UnsafeFnMarker, ::sus::iter::IterRefCounter refs, T* data, usize len) noexcept { ::sus::check(len <= ::sus::mog<usize>(isize::MAX)); return SliceMut(::sus::move(refs), data, len); } template <size_t N> requires(N <= ::sus::mog<usize>(isize::MAX_PRIMITIVE)) __attribute__((pure)) static constexpr inline SliceMut from( T (&data)[N]) { return SliceMut(::sus::iter::IterRefCounter::empty_for_view(), data, N); } __attribute__((pure)) constexpr SliceIterMut<T&> into_iter() && noexcept { return SliceIterMut<T&>::with( slice_.iter_refs_.to_iter_from_view(), slice_.data_, slice_.len_); } template <class U> requires(::sus::ops::Eq<T, U>) friend constexpr inline bool operator==(const SliceMut<T>& l, const SliceMut<U>& r) noexcept { return l.as_slice() == r.as_slice(); } template <class U> requires(!::sus::ops::Eq<T, U>) friend constexpr inline bool operator==(const SliceMut<T>& l, const SliceMut<U>& r) = delete; __attribute__((pure)) constexpr inline T& operator[](usize i) const& noexcept { ::sus::check(i < len()); return *(as_mut_ptr() + i); } __attribute__((pure)) constexpr inline SliceMut<T> operator[]( const ::sus::ops::RangeBounds<usize> auto range) const& noexcept { const usize length = len(); const usize rstart = range.start_bound().unwrap_or(0u); const usize rend = range.end_bound().unwrap_or(length); const usize rlen = rend >= rstart ? rend - rstart : 0u; ::sus::check(rlen <= length); ::sus::check(rstart <= length && rstart <= length - rlen); return SliceMut<T>::from_raw_parts_mut( ::sus::marker::unsafe_fn, slice_.iter_refs_.to_view_from_view(), as_mut_ptr() + rstart, rlen); } constexpr Slice<T> as_slice() const& noexcept { return *this; } __attribute__((pure)) constexpr operator const Slice<T>&() const& noexcept { return slice_; } __attribute__((pure)) constexpr operator Slice<T>&() & noexcept { return slice_; } __attribute__((pure)) constexpr operator Slice<T>() && noexcept { return ::sus::move(slice_); } void drop_iterator_invalidation_tracking(::sus::marker::UnsafeFnMarker) { slice_.iter_refs_ = ::sus::iter::IterRefCounter::empty_for_view(); } __attribute__((pure)) constexpr inline bool is_empty() const& noexcept { return len() == 0u; } __attribute__((pure)) constexpr inline ::sus::num::usize len() const& noexcept { return slice_.len_; } __attribute__((pure)) constexpr inline const T* as_ptr() const& noexcept { return slice_.data_; } __attribute__((pure)) constexpr ::sus::ops::Range<const T*> as_ptr_range() const& noexcept { return ::sus::ops::Range<const T*>(as_ptr(), as_ptr() + len()); } constexpr ::sus::result::Result<::sus::num::usize, ::sus::num::usize> binary_search(const T& x) const& noexcept requires(::sus::ops::Ord<T>) { return binary_search_by( [&x](const T& p) -> std::strong_ordering { return p <=> x; }); } constexpr ::sus::result::Result<::sus::num::usize, ::sus::num::usize> binary_search_by( ::sus::fn::FnMutRef<std::strong_ordering(const T&)> f) const& noexcept requires(::sus::ops::Ord<T>) { using Result = ::sus::result::Result<::sus::num::usize, ::sus::num::usize>; ::sus::num::usize size = len(); ::sus::num::usize left = 0u; ::sus::num::usize right = size; while (left < right) { auto mid = left + size / 2u; auto cmp = ::sus::fn::call_mut(f, get_unchecked(::sus::marker::unsafe_fn, mid)); if (cmp == std::strong_ordering::less) { left = mid + 1u; } else if (cmp == std::strong_ordering::greater) { right = mid; } else { static_assert(std::same_as<std::decay_t<decltype(::sus::marker::unsafe_fn)>, ::sus::marker::UnsafeFnMarker>); #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wassume" __builtin_assume(mid.primitive_value < slice_.len_.primitive_value) #pragma clang diagnostic pop ; return Result::with(mid); } size = right - left; } static_assert(std::same_as<std::decay_t<decltype(::sus::marker::unsafe_fn)>, ::sus::marker::UnsafeFnMarker>); #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wassume" __builtin_assume(left.primitive_value <= slice_.len_.primitive_value) #pragma clang diagnostic pop ; return Result::with_err(left); } template <::sus::ops::Ord Key> ::sus::result:: Result<::sus::num::usize, ::sus::num::usize> constexpr binary_search_by_key( const Key& key, ::sus::fn::FnMut<Key(const T&)> auto&& f) const& noexcept { return binary_search_by([&key, &f](const T& p) -> std::strong_ordering { return ::sus::fn::call_mut(f, p) <=> key; }); } constexpr Chunks<T> chunks(::sus::num::usize chunk_size) const& noexcept { return Chunks<T>::with(slice_.iter_refs_.to_iter_from_view(), *this, chunk_size); } constexpr ChunksExact<T> chunks_exact( ::sus::num::usize chunk_size) const& noexcept { return ChunksExact<T>::with(slice_.iter_refs_.to_iter_from_view(), *this, chunk_size); } using ConcatOutputType = ::sus::containers::Vec<T>; constexpr auto concat() const& noexcept requires(::sus::containers::Concat<T>) { const auto length = len(); ::sus::num::usize cap; for (::sus::num::usize i; i < length; i += 1u) { cap += get_unchecked(::sus::marker::unsafe_fn, i).len(); } using Container = typename T::ConcatOutputType; auto out = Container::with_capacity(cap); for (::sus::num::usize i; i < length; i += 1u) { get_unchecked(::sus::marker::unsafe_fn, i).concat_into(out); } return out; } constexpr void concat_into(::sus::containers::Vec<T>& vec) const& noexcept requires(::sus::mem::Clone<T>) { vec.extend_from_slice(*this); } constexpr bool contains(const T& x) const& noexcept requires(::sus::ops::Eq<T>) { const auto length = len(); const auto* const p = as_ptr(); for (::sus::num::usize i; i < length; i += 1u) { if (*(p + i) == x) return true; } return false; } constexpr bool ends_with(const Slice<T>& suffix) const& noexcept requires(::sus::ops::Eq<T>) { const auto m = len(); const auto n = suffix.len(); return m >= n && suffix == (*this)[::sus::ops::RangeFrom(m - n)]; } __attribute__((pure)) constexpr ::sus::Option<const T&> first() const& noexcept { if (len() > 0u) { return ::sus::Option<const T&>::with( get_unchecked(::sus::marker::unsafe_fn, 0u)); } else { return ::sus::Option<const T&>(); } } __attribute__((pure)) constexpr Option<const T&> get(::sus::num::usize i) const& noexcept { if (i < len()) [[likely]] return Option<const T&>::with(get_unchecked(::sus::marker::unsafe_fn, i)); else return Option<const T&>(); } __attribute__((pure)) constexpr inline const T& get_unchecked( ::sus::marker::UnsafeFnMarker, ::sus::num::usize i) const& noexcept { ::sus::check(i.primitive_value < slice_.len_.primitive_value); return as_ptr()[size_t{i}]; } __attribute__((pure)) constexpr Option<Slice<T>> get_range( const ::sus::ops::RangeBounds<::sus::num::usize> auto range) const& noexcept { const ::sus::num::usize length = len(); const ::sus::num::usize rstart = range.start_bound().unwrap_or(0u); const ::sus::num::usize rend = range.end_bound().unwrap_or(length); const ::sus::num::usize rlen = rend >= rstart ? rend - rstart : 0u; if (rlen > length) return sus::none(); if (rstart > length || rstart > length - rlen) return sus::none(); return Option<Slice<T>>::with(Slice<T>::from_raw_parts( ::sus::marker::unsafe_fn, slice_.iter_refs_.to_view_from_view(), as_ptr() + rstart, rlen)); } __attribute__((pure)) constexpr Slice<T> get_range_unchecked( ::sus::marker::UnsafeFnMarker, const ::sus::ops::RangeBounds<::sus::num::usize> auto range) const& noexcept { const ::sus::num::usize rstart = range.start_bound().unwrap_or(0u); const ::sus::num::usize rend = range.end_bound().unwrap_or(len()); const ::sus::num::usize rlen = rend >= rstart ? rend - rstart : 0u; return Slice<T>::from_raw_parts( ::sus::marker::unsafe_fn, slice_.iter_refs_.to_view_from_view(), as_ptr() + rstart, rlen); } __attribute__((pure)) constexpr SliceIter<const T&> iter() const& noexcept { return SliceIter<const T&>::with(slice_.iter_refs_.to_iter_from_view(), as_ptr(), len()); } using JoinOutputType = ::sus::containers::Vec<T>; template <class Sep> constexpr auto join(const Sep& separator) const& noexcept requires(::sus::containers::Join<T, Sep>) { const auto length = len(); ::sus::num::usize cap; for (::sus::num::usize i; i < length; i += 1u) { cap += get_unchecked(::sus::marker::unsafe_fn, i).len(); } using Container = typename T::JoinOutputType; auto out = Container::with_capacity(cap); if (length > 0u) get_unchecked(::sus::marker::unsafe_fn, 0u).join_into(out); for (::sus::num::usize i = 1u; i < length; i += 1u) { T::join_sep_into(out, separator); get_unchecked(::sus::marker::unsafe_fn, i).join_into(out); } return out; } constexpr void join_into(::sus::containers::Vec<T>& vec) const& noexcept requires(::sus::mem::Clone<T>) { vec.extend_from_slice(*this); } static constexpr void join_sep_into(::sus::containers::Vec<T>& vec, const Slice<T>& separator) noexcept requires(::sus::mem::Clone<T>) { vec.extend_from_slice(separator); } static constexpr void join_sep_into(::sus::containers::Vec<T>& vec, const T& separator) noexcept requires(::sus::mem::Clone<T>) { vec.push(::sus::clone(separator)); } __attribute__((pure)) constexpr ::sus::Option<const T&> last() const& noexcept { const auto length = len(); if (length > 0u) return ::sus::Option<const T&>::with(*(as_ptr() + length - 1u)); else return ::sus::Option<const T&>(); } constexpr ::sus::num::usize partition_point( ::sus::fn::FnMutRef<bool(const T&)> pred) const& noexcept { return binary_search_by([pred = ::sus::move(pred)](const T& x) { if (::sus::fn::call_mut(pred, x)) { return std::strong_ordering::less; } else { return std::strong_ordering::greater; } }) .unwrap_or_else([](::sus::num::usize i) { return i; }); } constexpr RChunks<T> rchunks(::sus::num::usize chunk_size) const& noexcept { return RChunks<T>::with(slice_.iter_refs_.to_iter_from_view(), *this, chunk_size); } constexpr RChunksExact<T> rchunks_exact( ::sus::num::usize chunk_size) const& noexcept { return RChunksExact<T>::with(slice_.iter_refs_.to_iter_from_view(), *this, chunk_size); } constexpr ::sus::containers::Vec<T> repeat(usize n) const& noexcept requires(::sus::mem::TrivialCopy<T>) { auto buf = ::sus::containers::Vec<T>(); if (n == 0u) return buf; const usize l = len(); const usize capacity = l.saturating_mul(n); buf.reserve(capacity); buf.extend(iter()); { usize m = n >> 1u; while (m > 0u) { ::sus::ptr::copy_nonoverlapping(::sus::marker::unsafe_fn, buf.as_ptr(), buf.as_mut_ptr() + buf.len(), buf.len()); const usize buf_len = buf.len(); buf.set_len(::sus::marker::unsafe_fn, buf_len * 2u); m >>= 1u; } } const usize rem_len = capacity - buf.len(); if (rem_len > 0u) { ::sus::ptr::copy_nonoverlapping(::sus::marker::unsafe_fn, buf.as_ptr(), buf.as_mut_ptr() + buf.len(), rem_len); buf.set_len(::sus::marker::unsafe_fn, capacity); } return buf; } constexpr RSplit<T> rsplit( ::sus::fn::FnMutRef<bool(const T&)> pred) const& noexcept { return RSplit<T>::with( Split<T>::with(slice_.iter_refs_.to_iter_from_view(), *this, ::sus::move(pred))); } constexpr RSplitN<T> rsplitn( usize n, ::sus::fn::FnMutRef<bool(const T&)> pred) const& noexcept { return RSplitN<T>::with(RSplit<T>::with(Split<T>::with(slice_.iter_refs_.to_iter_from_view(), *this, ::sus::move(pred))), n); } constexpr Split<T> split( ::sus::fn::FnMutRef<bool(const T&)> pred) const& noexcept { return Split<T>::with(slice_.iter_refs_.to_iter_from_view(), *this, ::sus::move(pred)); } __attribute__((pure)) constexpr ::sus::Tuple<Slice<T>, Slice<T>> split_at( ::sus::num::usize mid) const& noexcept { ::sus::check(mid <= len()); return split_at_unchecked(::sus::marker::unsafe_fn, mid); } __attribute__((pure)) constexpr ::sus::Tuple<Slice<T>, Slice<T>> split_at_unchecked( ::sus::marker::UnsafeFnMarker, ::sus::num::usize mid) const& noexcept { ::sus::check(mid.primitive_value <= slice_.len_.primitive_value); const ::sus::num::usize rem = len().unchecked_sub(::sus::marker::unsafe_fn, mid); return ::sus::Tuple<Slice<T>, Slice<T>>::with( Slice<T>::from_raw_parts(::sus::marker::unsafe_fn, slice_.iter_refs_.to_view_from_view(), as_ptr(), mid), Slice<T>::from_raw_parts(::sus::marker::unsafe_fn, slice_.iter_refs_.to_view_from_view(), as_ptr() + mid, rem)); } __attribute__((pure)) constexpr ::sus::Option<::sus::Tuple<const T&, Slice<T>>> split_first() const& noexcept { if (is_empty()) return ::sus::none(); return ::sus::some( ::sus::tuple(*as_ptr(), (*this)[::sus::ops::RangeFrom<usize>(1u)])); } constexpr SplitInclusive<T> split_inclusive( ::sus::fn::FnMutRef<bool(const T&)> pred) const& noexcept { return SplitInclusive<T>::with(slice_.iter_refs_.to_iter_from_view(), *this, ::sus::move(pred)); } __attribute__((pure)) constexpr ::sus::Option<::sus::Tuple<const T&, Slice<T>>> split_last() const& noexcept { if (is_empty()) return ::sus::none(); const usize last = len() - 1u; return ::sus::some(::sus::tuple(*(as_ptr() + last), (*this)[::sus::ops::RangeTo<usize>(last)])); } constexpr SplitN<T> splitn( usize n, ::sus::fn::FnMutRef<bool(const T&)> pred) const& noexcept { return SplitN<T>::with( Split<T>::with(slice_.iter_refs_.to_iter_from_view(), *this, ::sus::move(pred)), n); } constexpr bool starts_with(const Slice<T>& needle) const& requires(::sus::ops::Eq<T>) { const auto n = needle.len(); return len() >= n && needle == (*this)[::sus::ops::RangeTo(n)]; } constexpr ::sus::Option<Slice<T>> strip_prefix( const Slice<T>& prefix) const& noexcept requires(::sus::ops::Eq<T>) { const usize n = prefix.len(); if (n <= len()) { auto [head, tail] = split_at(n); if (head == prefix) { return ::sus::Option<Slice<T>>::with(tail); } } return ::sus::Option<Slice<T>>(); } constexpr ::sus::Option<Slice<T>> strip_suffix( const Slice<T>& suffix) const& noexcept requires(::sus::ops::Eq<T>) { const auto l = len(); const auto n = suffix.len(); if (n <= l) { auto [head, tail] = split_at(l - n); if (tail == suffix) { return ::sus::Option<Slice<T>>::with(head); } } return ::sus::Option<Slice<T>>(); } Vec<T> to_vec() const& noexcept requires(::sus::mem::Clone<T>); __attribute__((pure)) constexpr Windows<T> windows(usize size) const& noexcept { ::sus::check(size > 0u); return Windows<T>::with(slice_.iter_refs_.to_iter_from_view(), *this, size); } __attribute__((pure)) constexpr inline T* as_mut_ptr() const& noexcept { return slice_.data_; } __attribute__((pure)) constexpr ::sus::ops::Range<T*> as_mut_ptr_range() const& noexcept { return ::sus::ops::Range<T*>(as_mut_ptr(), as_mut_ptr() + len()); } constexpr ChunksExactMut<T> chunks_exact_mut(::sus::num::usize chunk_size) const& noexcept { return ChunksExactMut<T>::with(slice_.iter_refs_.to_iter_from_view(), *this, chunk_size); } constexpr ChunksMut<T> chunks_mut(::sus::num::usize chunk_size) const& noexcept { return ChunksMut<T>::with(slice_.iter_refs_.to_iter_from_view(), *this, chunk_size); } constexpr void copy_from_slice(const Slice<T>& src) const& noexcept requires(::sus::mem::TrivialCopy<T>) { const ::sus::num::usize src_len = src.len(); const ::sus::num::usize dst_len = len(); ::sus::check(dst_len == src_len); const T* const src_ptr = src.as_ptr(); T* const dst_ptr = as_mut_ptr(); ::sus::check((src_ptr < dst_ptr && src_ptr <= dst_ptr - src_len) || (dst_ptr < src_ptr && dst_ptr <= src_ptr - dst_len)); if (std::is_constant_evaluated()) { for (::sus::num::usize i; i < dst_len; i += 1u) *(dst_ptr + i) = *(src_ptr + i); } else { if constexpr (::sus::mem::size_of<T>() > 1u) { constexpr auto max_len = ::sus::num::usize::MAX / ::sus::mem::size_of<T>(); if (dst_len > max_len) { for (::sus::num::usize i; i < dst_len; i += 1u) *(dst_ptr + i) = *(src_ptr + i); return; } } ::sus::ptr::copy_nonoverlapping(::sus::marker::unsafe_fn, src_ptr, dst_ptr, dst_len); } } constexpr void copy_from_slice_unchecked( ::sus::marker::UnsafeFnMarker, const Slice<T>& src) const& noexcept requires(std::is_trivially_copy_assignable_v<T>) { const ::sus::num::usize dst_len = len(); const T* const src_ptr = src.as_ptr(); T* const dst_ptr = as_mut_ptr(); ::sus::check((src_ptr < dst_ptr && src_ptr <= dst_ptr - dst_len.primitive_value) || (dst_ptr < src_ptr && dst_ptr <= src_ptr - dst_len.primitive_value)); if (std::is_constant_evaluated()) { for (::sus::num::usize i; i < dst_len; i += 1u) *(dst_ptr + i) = *(src_ptr + i); } else { ::sus::ptr::copy_nonoverlapping(::sus::marker::unsafe_fn, src_ptr, dst_ptr, dst_len); } } constexpr void clone_from_slice(const Slice<T>& src) const& noexcept requires(::sus::mem::Clone<T>) { const ::sus::num::usize src_len = src.len(); const ::sus::num::usize dst_len = len(); ::sus::check(dst_len == src_len); const T* const src_ptr = src.as_ptr(); T* dst_ptr = as_mut_ptr(); for (::sus::num::usize i; i < dst_len; i += 1u) { ::sus::clone_into(*(dst_ptr + i), *(src_ptr + i)); } } constexpr void fill(T value) const& noexcept requires(::sus::mem::Clone<T>) { T* ptr = as_mut_ptr(); T* const end_ptr = ptr + len(); while (ptr != end_ptr) { ::sus::clone_into(*ptr, value); ptr += 1u; } } constexpr void fill_with(::sus::fn::FnMutRef<T()> f) const& noexcept { T* ptr = as_mut_ptr(); T* const end_ptr = ptr + len(); while (ptr != end_ptr) { *ptr = ::sus::fn::call_mut(f); ptr += 1u; } } constexpr void fill_with_default() const& noexcept requires(sus::construct::Default<T>) { T* ptr = as_mut_ptr(); T* const end_ptr = ptr + len(); while (ptr != end_ptr) { *ptr = T(); ptr += 1u; } } __attribute__((pure)) constexpr ::sus::Option<T&> first_mut() const& noexcept { if (len() > 0u) return ::sus::Option<T&>::with(*as_mut_ptr()); else return ::sus::Option<T&>(); } __attribute__((pure)) constexpr Option<T&> get_mut(::sus::num::usize i) const& noexcept { if (i < len()) [[likely]] return Option<T&>::with(get_unchecked_mut(::sus::marker::unsafe_fn, i)); else return Option<T&>(); } __attribute__((pure)) constexpr inline T& get_unchecked_mut( ::sus::marker::UnsafeFnMarker, ::sus::num::usize i) const& noexcept { ::sus::check(i.primitive_value < slice_.len_.primitive_value); return as_mut_ptr()[size_t{i}]; } __attribute__((pure)) constexpr Option<SliceMut<T>> get_range_mut( const ::sus::ops::RangeBounds<::sus::num::usize> auto range) const& noexcept { const ::sus::num::usize length = len(); const ::sus::num::usize rstart = range.start_bound().unwrap_or(0u); const ::sus::num::usize rend = range.end_bound().unwrap_or(length); const ::sus::num::usize rlen = rend >= rstart ? rend - rstart : 0u; if (rlen > length) return sus::none(); if (rstart > length || rstart > length - rlen) return sus::none(); return Option<SliceMut<T>>::with(SliceMut<T>::from_raw_parts_mut( ::sus::marker::unsafe_fn, slice_.iter_refs_.to_view_from_view(), as_mut_ptr() + rstart, rlen)); } __attribute__((pure)) constexpr SliceMut<T> get_range_mut_unchecked( ::sus::marker::UnsafeFnMarker, const ::sus::ops::RangeBounds<::sus::num::usize> auto range) const& noexcept { const ::sus::num::usize rstart = range.start_bound().unwrap_or(0u); const ::sus::num::usize rend = range.end_bound().unwrap_or(len()); const ::sus::num::usize rlen = rend >= rstart ? rend - rstart : 0u; return SliceMut<T>::from_raw_parts_mut(::sus::marker::unsafe_fn, slice_.iter_refs_.to_view_from_view(), as_mut_ptr() + rstart, rlen); } __attribute__((pure)) constexpr SliceIterMut<T&> iter_mut() const& noexcept { return SliceIterMut<T&>::with(slice_.iter_refs_.to_iter_from_view(), as_mut_ptr(), len()); } __attribute__((pure)) constexpr ::sus::Option<T&> last_mut() const& noexcept { const ::sus::num::usize length = len(); if (length > 0u) return ::sus::Option<T&>::with(*(as_mut_ptr() + length - 1u)); else return ::sus::Option<T&>(); } constexpr RChunksExactMut<T> rchunks_exact_mut(::sus::num::usize chunk_size) const& noexcept { return RChunksExactMut<T>::with(slice_.iter_refs_.to_iter_from_view(), *this, chunk_size); } constexpr RChunksMut<T> rchunks_mut(::sus::num::usize chunk_size) const& noexcept { return RChunksMut<T>::with(slice_.iter_refs_.to_iter_from_view(), *this, chunk_size); } constexpr void reverse() const& noexcept requires(::sus::mem::Move<T>) { const auto half_len = len() / 2u; const auto [start, end] = as_mut_ptr_range(); auto front_half = ::sus::containers::SliceMut<T>::from_raw_parts_mut( ::sus::marker::unsafe_fn, slice_.iter_refs_.to_view_from_view(), start, half_len); auto back_half = ::sus::containers::SliceMut<T>::from_raw_parts_mut( ::sus::marker::unsafe_fn, slice_.iter_refs_.to_view_from_view(), end - half_len, half_len); for (::sus::num::usize i; i < half_len; i += 1u) { ::sus::mem::swap_nonoverlapping(::sus::marker::unsafe_fn, front_half[i], back_half[half_len - 1u - i]); } } void rotate_left(::sus::num::usize mid) const& noexcept requires(::sus::mem::Move<T>) { const ::sus::num::usize length = len(); ::sus::check(mid <= length); const ::sus::num::usize k = length - mid; T* const p = as_mut_ptr(); if constexpr (::sus::mem::relocate_by_memcpy<T>) { if (!std::is_constant_evaluated()) { } } if (mid == 0u || k == 0u) return; for (::sus::num::usize i; i < k; i += 1u) { ::sus::mem::swap_nonoverlapping(::sus::marker::unsafe_fn, *(p + i), *(p + mid + i)); } if (k < mid) { get_range_mut_unchecked(::sus::marker::unsafe_fn, ::sus::ops::RangeFrom(k)) .rotate_left(mid - k); } else if (k > mid && mid % 2u != (k - mid) % 2u) { if ((k - mid) % 2u == 1u) { for (::sus::num::usize i = k; i < length - 1u; i += 1u) { ::sus::mem::swap_nonoverlapping(::sus::marker::unsafe_fn, *(p + i), *(p + length - 1u)); } } else { for (::sus::num::usize i = k; i < length - 1u; i += 1u) { ::sus::mem::swap_nonoverlapping(::sus::marker::unsafe_fn, *(p + i), *(p + i + 1u)); } } } } void rotate_right(::sus::num::usize k) const& noexcept requires(::sus::mem::Move<T>) { rotate_left(len() - k); } constexpr RSplitMut<T> rsplit_mut(::sus::fn::FnMutRef<bool(const T&)> pred) const& noexcept { return RSplitMut<T>::with( SplitMut<T>::with(slice_.iter_refs_.to_iter_from_view(), *this, ::sus::move(pred))); } constexpr RSplitNMut<T> rsplitn_mut( usize n, ::sus::fn::FnMutRef<bool(const T&)> pred) const& noexcept { return RSplitNMut<T>::with(RSplitMut<T>::with(SplitMut<T>::with( slice_.iter_refs_.to_iter_from_view(), *this, ::sus::move(pred))), n); } void sort() const& noexcept requires(::sus::ops::Ord<T>) { if (len() > ::sus::num::usize(0u)) { std::stable_sort(as_mut_ptr(), as_mut_ptr() + len()); } } void sort_by(::sus::fn::FnMutRef<std::strong_ordering(const T&, const T&)> compare) const& noexcept { if (len() > ::sus::num::usize(0u)) { std::stable_sort(as_mut_ptr(), as_mut_ptr() + len(), [&compare](const T& l, const T& r) { return ::sus::fn::call_mut(compare, l, r) < 0; }); } } template <::sus::fn::FnMut<::sus::fn::NonVoid(const T&)> KeyFn, int&..., class Key = std::invoke_result_t<KeyFn&, const T&>> requires(::sus::ops::Ord<Key>) void sort_by_key(KeyFn f) const& noexcept { return sort_by([&f](const T& a, const T& b) { return ::sus::fn::call_mut(f, a) <=> ::sus::fn::call_mut(f, b); }); } template <::sus::fn::FnMut<::sus::fn::NonVoid(const T&)> KeyFn, int&..., class Key = std::invoke_result_t<KeyFn&, const T&>> requires(::sus::ops::Ord<Key>) void sort_by_cached_key(KeyFn f) const& noexcept { constexpr auto sz_u8 = ::sus::mem::size_of<::sus::Tuple<Key, u8>>(); constexpr auto sz_u16 = ::sus::mem::size_of<::sus::Tuple<Key, u16>>(); constexpr auto sz_u32 = ::sus::mem::size_of<::sus::Tuple<Key, u32>>(); constexpr auto sz_usize = ::sus::mem::size_of<::sus::Tuple<Key, usize>>(); const auto length = len(); if (length < 2u) { return; } if constexpr (sz_u8 < sz_u16) { if (length <= u8::MAX) { __private::sort_slice_by_cached_key<u8, Key, T>(*this, f); return; } } if constexpr (sz_u16 < sz_u32) { if (length <= u16::MAX) { __private::sort_slice_by_cached_key<u16, Key, T>(*this, f); return; } } if constexpr (sz_u32 < sz_usize) { if (length <= u32::MAX) { __private::sort_slice_by_cached_key<u32, Key, T>(*this, f); return; } } __private::sort_slice_by_cached_key<usize, Key, T>(*this, f); } constexpr void sort_unstable() const& noexcept requires(::sus::ops::Ord<T>) { if (len() > 0u) { std::sort(as_mut_ptr(), as_mut_ptr() + len()); } } constexpr void sort_unstable_by( ::sus::fn::FnMutRef<std::strong_ordering(const T&, const T&)> compare) const& noexcept { if (len() > 0u) { std::sort(as_mut_ptr(), as_mut_ptr() + len(), [&compare](const T& l, const T& r) { return ::sus::fn::call_mut(compare, l, r) < 0; }); } } template <::sus::fn::FnMut<::sus::fn::NonVoid(const T&)> KeyFn, int&..., class Key = std::invoke_result_t<KeyFn&, const T&>> requires(::sus::ops::Ord<Key>) void sort_unstable_by_key(KeyFn f) const& noexcept { return sort_unstable_by([&f](const T& a, const T& b) { return ::sus::fn::call_mut(f, a) <=> ::sus::fn::call_mut(f, b); }); } constexpr SplitMut<T> split_mut(::sus::fn::FnMutRef<bool(const T&)> pred) const& noexcept { return SplitMut<T>::with(slice_.iter_refs_.to_iter_from_view(), *this, ::sus::move(pred)); } __attribute__((pure)) constexpr ::sus::Tuple<SliceMut<T>, SliceMut<T>> split_at_mut( ::sus::num::usize mid) const& noexcept { ::sus::check(mid <= len()); return split_at_mut_unchecked(::sus::marker::unsafe_fn, mid); } __attribute__((pure)) constexpr ::sus::Tuple<SliceMut<T>, SliceMut<T>> split_at_mut_unchecked(::sus::marker::UnsafeFnMarker, ::sus::num::usize mid) const& noexcept { ::sus::check(mid.primitive_value <= slice_.len_.primitive_value); const ::sus::num::usize rem = len().unchecked_sub(::sus::marker::unsafe_fn, mid); return ::sus::Tuple<SliceMut<T>, SliceMut<T>>::with( SliceMut<T>::from_raw_parts_mut(::sus::marker::unsafe_fn, slice_.iter_refs_.to_view_from_view(), as_mut_ptr(), mid), SliceMut<T>::from_raw_parts_mut(::sus::marker::unsafe_fn, slice_.iter_refs_.to_view_from_view(), as_mut_ptr() + mid, rem)); } __attribute__((pure)) constexpr ::sus::Option<::sus::Tuple<T&, SliceMut<T>>> split_first_mut() const& noexcept { if (is_empty()) return ::sus::none(); return ::sus::some( ::sus::tuple(*as_mut_ptr(), get_range_mut_unchecked(::sus::marker::unsafe_fn, ::sus::ops::RangeFrom<usize>(1u)))); } constexpr SplitInclusiveMut<T> split_inclusive_mut( ::sus::fn::FnMutRef<bool(const T&)> pred) const& noexcept { return SplitInclusiveMut<T>::with(slice_.iter_refs_.to_iter_from_view(), *this, ::sus::move(pred)); } __attribute__((pure)) constexpr ::sus::Option<::sus::Tuple<T&, SliceMut<T>>> split_last_mut() const& noexcept { if (is_empty()) return ::sus::none(); const usize last = len() - 1u; return ::sus::some( ::sus::tuple(*(as_mut_ptr() + last), get_range_mut_unchecked(::sus::marker::unsafe_fn, ::sus::ops::RangeTo<usize>(last)))); } constexpr SplitNMut<T> splitn_mut( usize n, ::sus::fn::FnMutRef<bool(const T&)> pred) const& noexcept { return SplitNMut<T>::with( SplitMut<T>::with(slice_.iter_refs_.to_iter_from_view(), *this, ::sus::move(pred)), n); } constexpr ::sus::Option<SliceMut<T>> strip_prefix_mut(const Slice<T>& prefix) const& noexcept requires(::sus::ops::Eq<T>) { const usize n = prefix.len(); if (n <= len()) { auto [head, tail] = split_at_mut(n); if (head == prefix) { return ::sus::Option<SliceMut<T>>::with(tail); } } return ::sus::Option<SliceMut<T>>(); } constexpr ::sus::Option<SliceMut<T>> strip_suffix_mut(const Slice<T>& suffix) const& noexcept requires(::sus::ops::Eq<T>) { const auto l = len(); const auto n = suffix.len(); if (n <= l) { auto [head, tail] = split_at_mut(l - n); if (tail == suffix) { return ::sus::Option<SliceMut<T>>::with(head); } } return ::sus::Option<SliceMut<T>>(); } constexpr void swap(usize a, usize b) const& noexcept { ::sus::check(a < len() && b < len()); ::sus::mem::swap(*(as_mut_ptr() + a), *(as_mut_ptr() + b)); } constexpr void swap_nonoverlapping(::sus::marker::UnsafeFnMarker, usize a, usize b) const& noexcept { ::sus::check(a.primitive_value != b.primitive_value); ::sus::check(a.primitive_value < slice_.len_.primitive_value); ::sus::check(b.primitive_value < slice_.len_.primitive_value); ::sus::mem::swap_nonoverlapping(::sus::marker::unsafe_fn, *(as_mut_ptr() + a), *(as_mut_ptr() + b)); } constexpr void swap_unchecked(::sus::marker::UnsafeFnMarker, usize a, usize b) const& noexcept { ::sus::check(a.primitive_value < slice_.len_.primitive_value); ::sus::check(b.primitive_value < slice_.len_.primitive_value); ::sus::mem::swap(*(as_mut_ptr() + a), *(as_mut_ptr() + b)); } constexpr void swap_with_slice(const SliceMut<T>& other) const& noexcept { auto const self_len = len(); auto const other_len = other.len(); T* const self_ptr = as_mut_ptr(); T* const other_ptr = other.as_mut_ptr(); ::sus::check(self_len == other_len); if (other_ptr <= self_ptr) { ::sus::check(other_ptr + other_len <= self_ptr); } else { ::sus::check(self_ptr + self_len <= other_ptr); } ::sus::ptr::swap_nonoverlapping(::sus::marker::unsafe_fn, self_ptr, other_ptr, self_len); } __attribute__((pure)) constexpr WindowsMut<T> windows_mut(usize size) const& noexcept { ::sus::check(size > 0u); return WindowsMut<T>::with(slice_.iter_refs_.to_iter_from_view(), *this, size); } private: constexpr SliceMut(sus::iter::IterRefCounter refs, T* data, usize len) : slice_(::sus::move(refs), data, len) {} template <class VecT> friend class Vec; Slice<T> slice_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(slice_)>; static_assert(SusUnsafeTrivialRelocate, "Type is not trivially relocatable"); }; template <class T> Vec<T> SliceMut<T>::to_vec() const& noexcept requires(::sus::mem::Clone<T>) { auto v = Vec<T>::with_capacity(slice_.len_); for (::sus::usize i; i < slice_.len_; i += 1u) { v.push(::sus::clone(*(slice_.data_ + i))); } return v; } using ::sus::iter::__private::begin; using ::sus::iter::__private::end; } namespace sus { using ::sus::containers::Slice; using ::sus::containers::SliceMut; } namespace sus::containers { namespace __private { template <class T, size_t N> struct Storage final { [[no_unique_address]] sus::iter::IterRefCounter iter_refs_; T data_[N]; }; template <class T> struct Storage<T, 0> final {}; } template <class T, size_t N> class Array final { static_assert(N <= ::sus::mog<usize>(isize::MAX)); static_assert(!std::is_reference_v<T>, "Array<T&, N> is invalid as Array must hold value types. Use " "Array<T*, N> instead."); static_assert(!std::is_const_v<T>, "`Array<const T, N>` should be written `const Array<T, N>`, as " "const applies transitively."); public: constexpr Array() noexcept requires(::sus::construct::Default<T>) : Array(kWithDefault, std::make_index_sequence<N>()) {} constexpr static Array with_initializer( ::sus::fn::FnMut<T()> auto&& f) noexcept { if constexpr (N == 0) return Array(); else return Array(kWithInitializer, f, std::make_index_sequence<N>()); } template <std::convertible_to<T> U> requires(::sus::mem::Copy<T>) constexpr static Array with_value(U&& t) noexcept { if constexpr (N == 0) return Array(); else return Array(kWithValue, t, std::make_index_sequence<N>()); } template <std::convertible_to<T>... Ts> requires(sizeof...(Ts) == N) constexpr static Array with(Ts&&... ts) noexcept { if constexpr (N == 0) return Array(); else return Array(kWithValues, ::sus::forward<Ts>(ts)...); } Array(Array&&) requires(N == 0 && ::sus::mem::Move<T>) = default; Array& operator=(Array&&) requires(N == 0 && ::sus::mem::Move<T>) = default; constexpr Array(Array&& o) noexcept requires(N > 0 && ::sus::mem::Move<T>) : Array(kWithMoveFromPointer, o.storage_.data_, o.storage_.iter_refs_.take_for_owner(), std::make_index_sequence<N>()) { ::sus::check(!has_iterators()); } constexpr Array& operator=(Array&& o) noexcept requires(::sus::mem::Move<T>) { ::sus::check(!has_iterators()); ::sus::check(!o.has_iterators()); for (auto i = size_t{0}; i < N; ++i) storage_.data_[i] = ::sus::mem::take(o.storage_.data_[i]); storage_.iter_refs_ = o.storage_.iter_refs_.take_for_owner(); return *this; } Array(Array&&) requires(!::sus::mem::Move<T>) = delete; Array& operator=(Array&&) requires(!::sus::mem::Move<T>) = delete; constexpr Array clone() const& noexcept requires(::sus::mem::Clone<T>) { if constexpr (N == 0) { return Array(); } else { return Array(kWithCloneFromPointer, storage_.data_, std::make_index_sequence<N>()); } } constexpr void clone_from(const Array& source) & noexcept requires(::sus::mem::Clone<T>) { if constexpr (N > 0) { if (&source == this) [[unlikely]] return; for (auto i = size_t{0}; i < N; ++i) { ::sus::clone_into(get_unchecked_mut(::sus::marker::unsafe_fn, i), source.get_unchecked(::sus::marker::unsafe_fn, i)); } } } ~Array() requires(std::is_trivially_destructible_v<T>) = default; constexpr ~Array() requires(!std::is_trivially_destructible_v<T>) { for (auto i = size_t{0}; i < N; ++i) storage_.data_[i].~T(); } constexpr usize len() const& noexcept { return N; } constexpr Option<const T&> get(usize i) const& noexcept requires(N > 0) { if (i.primitive_value >= N) [[unlikely]] return Option<const T&>(); return Option<const T&>::with(storage_.data_[i.primitive_value]); } constexpr Option<const T&> get(usize i) && = delete; constexpr Option<T&> get_mut(usize i) & noexcept requires(N > 0) { if (i.primitive_value >= N) [[unlikely]] return Option<T&>(); return Option<T&>::with(storage_.data_[i.primitive_value]); } constexpr inline const T& get_unchecked( ::sus::marker::UnsafeFnMarker, usize i) const& noexcept requires(N > 0) { return storage_.data_[i.primitive_value]; } constexpr inline const T& get_unchecked(::sus::marker::UnsafeFnMarker, usize i) && = delete; constexpr inline T& get_unchecked_mut(::sus::marker::UnsafeFnMarker, usize i) & noexcept requires(N > 0) { return storage_.data_[i.primitive_value]; } constexpr inline const T& operator[](usize i) const& noexcept { check(i.primitive_value < N); return storage_.data_[i.primitive_value]; } constexpr inline const T& operator[](usize i) && = delete; constexpr inline T& operator[](usize i) & noexcept { check(i.primitive_value < N); return storage_.data_[i.primitive_value]; } constexpr inline const T* as_ptr() const& noexcept requires(N > 0) { return storage_.data_; } const T* as_ptr() && = delete; constexpr inline T* as_mut_ptr() & noexcept requires(N > 0) { return storage_.data_; } constexpr Slice<T> as_slice() const& noexcept { return Slice<T>::from(storage_.data_); } constexpr Slice<T> as_slice() && = delete; constexpr SliceMut<T> as_mut_slice() & noexcept { return SliceMut<T>::from(storage_.data_); } constexpr SliceIter<const T&> iter() const& noexcept { if constexpr (N == 0) { return SliceIter<const T&>::with( sus::iter::IterRefCounter::empty_for_view().to_iter_from_view(), nullptr, N); } else { return SliceIter<const T&>::with(storage_.iter_refs_.to_iter_from_owner(), storage_.data_, N); } } constexpr SliceIter<const T&> iter() && = delete; constexpr SliceIterMut<T&> iter_mut() & noexcept { if constexpr (N == 0) { return SliceIterMut<T&>::with( sus::iter::IterRefCounter::empty_for_view().to_iter_from_view(), nullptr, N); } else { return SliceIterMut<T&>::with(storage_.iter_refs_.to_iter_from_owner(), storage_.data_, N); } } template <int&..., class U = T> constexpr ArrayIntoIter<U, N> into_iter() && noexcept requires(::sus::mem::Move<T>) { return ArrayIntoIter<T, N>::with(::sus::move(*this)); } template <::sus::fn::FnMut<::sus::fn::NonVoid(T&&)> MapFn, int&..., class R = std::invoke_result_t<MapFn&&, T&&>> requires(N > 0) Array<R, N> map(MapFn f) && noexcept { return Array<R, N>::with_initializer([this, &f, i = size_t{0}]() mutable { return f(::sus::move(storage_.data_[i++])); }); } template <class U> requires(::sus::ops::Eq<T, U>) constexpr bool operator==(const Array<U, N>& r) const& noexcept requires(::sus::ops::Eq<T>) { return eq_impl(r, std::make_index_sequence<N>()); } private: enum WithDefault { kWithDefault }; template <size_t... Is> requires(N == 0) constexpr Array(WithDefault, std::index_sequence<Is...>) noexcept {} template <size_t... Is> requires(N > 0) constexpr Array(WithDefault, std::index_sequence<Is...>) noexcept : storage_(::sus::iter::IterRefCounter::for_owner(), {((void)Is, T())...}) {} enum WithInitializer { kWithInitializer }; template <size_t... Is> requires(N > 0) constexpr Array(WithInitializer, ::sus::fn::FnMut<T()> auto&& f, std::index_sequence<Is...>) noexcept : storage_(::sus::iter::IterRefCounter::for_owner(), {((void)Is, ::sus::fn::call_mut(f))...}) {} enum WithValue { kWithValue }; template <size_t... Is> requires(N > 0) constexpr Array(WithValue, const T& t, std::index_sequence<Is...>) noexcept : storage_(::sus::iter::IterRefCounter::for_owner(), {((void)Is, t)...}) { } enum WithValues { kWithValues }; template <class... Ts> requires(N > 0) constexpr Array(WithValues, Ts&&... ts) noexcept : storage_(::sus::iter::IterRefCounter::for_owner(), {::sus::forward<Ts>(ts)...}) {} enum WithMoveFromPointer { kWithMoveFromPointer }; template <size_t... Is> requires(N > 0) constexpr Array(WithMoveFromPointer, T* t, ::sus::iter::IterRefCounter refs, std::index_sequence<Is...>) noexcept : storage_(::sus::move(refs), {::sus::move(*(t + Is))...}) {} enum WithCloneFromPointer { kWithCloneFromPointer }; template <size_t... Is> requires(N > 0) constexpr Array(WithCloneFromPointer, const T* t, std::index_sequence<Is...>) noexcept : storage_(::sus::iter::IterRefCounter::for_owner(), {::sus::clone(*(t + Is))...}) {} constexpr inline bool has_iterators() const noexcept requires(N > 0) { return storage_.iter_refs_.count_from_owner() != 0u; } template <class U, size_t... Is> constexpr inline auto eq_impl(const Array<U, N>& r, std::index_sequence<Is...>) const& noexcept { return (... && (get_unchecked(::sus::marker::unsafe_fn, Is) == r.get_unchecked(::sus::marker::unsafe_fn, Is))); }; ::sus::containers::__private::Storage<T, N> storage_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); static_assert( std::is_same_v<std::remove_cv_t<decltype((N == 0 || ::sus::mem::relocate_by_memcpy<T>))>, bool>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = (N == 0 || ::sus::mem::relocate_by_memcpy<T>); }; namespace __private { template <size_t I, class O, class T, class U, size_t N> constexpr inline bool array_cmp_impl(O& val, const Array<T, N>& l, const Array<U, N>& r) noexcept { auto cmp = l.get_unchecked(::sus::marker::unsafe_fn, I) <=> r.get_unchecked(::sus::marker::unsafe_fn, I); if (cmp != 0) val = cmp; return val == 0; }; template <class T, class U, size_t N, size_t... Is> constexpr inline auto array_cmp(auto equal, const Array<T, N>& l, const Array<U, N>& r, std::index_sequence<Is...>) noexcept { auto val = equal; (true && ... && (array_cmp_impl<Is>(val, l, r))); return val; }; } template <class T, class U, size_t N> requires(::sus::ops::ExclusiveOrd<T, U>) constexpr inline auto operator<=>(const Array<T, N>& l, const Array<U, N>& r) noexcept { return __private::array_cmp(std::strong_ordering::equivalent, l, r, std::make_index_sequence<N>()); } template <class T, class U, size_t N> requires(::sus::ops::ExclusiveWeakOrd<T, U>) constexpr inline auto operator<=>(const Array<T, N>& l, const Array<U, N>& r) noexcept { return __private::array_cmp(std::weak_ordering::equivalent, l, r, std::make_index_sequence<N>()); } template <class T, class U, size_t N> requires(::sus::ops::ExclusivePartialOrd<T, U>) constexpr inline auto operator<=>(const Array<T, N>& l, const Array<U, N>& r) noexcept { return __private::array_cmp(std::partial_ordering::equivalent, l, r, std::make_index_sequence<N>()); } using ::sus::iter::__private::begin; using ::sus::iter::__private::end; template <size_t I, class T, size_t N> const auto& get(const Array<T, N>& a) noexcept { return a.get_unchecked(::sus::marker::unsafe_fn, I); } template <size_t I, class T, size_t N> auto& get(Array<T, N>& a) noexcept { return a.get_unchecked_mut(::sus::marker::unsafe_fn, I); } template <size_t I, class T, size_t N> auto get(Array<T, N>&& a) noexcept { return ::sus::move(a.get_unchecked_mut(::sus::marker::unsafe_fn, I)); } template <class... Ts> requires(sizeof...(Ts) > 0) [[nodiscard]] inline constexpr auto array( Ts&&... vs) noexcept { return __private::ArrayMarker<Ts...>( ::sus::tuple_type::Tuple<Ts&&...>::with(::sus::forward<Ts>(vs)...)); } } namespace std { template <class T, size_t N> struct tuple_size<::sus::containers::Array<T, N>> { static constexpr size_t value = N; }; template <size_t I, class T, size_t N> struct tuple_element<I, ::sus::containers::Array<T, N>> { using type = T; }; } namespace sus { using ::sus::containers::array; using ::sus::containers::Array; } namespace sus::num { template <Unsigned U> __attribute__((pure)) constexpr ::sus::result::Result<u32, ::sus::num::TryFromIntError> u32::try_from(U u) noexcept { using R = ::sus::result::Result<u32, ::sus::num::TryFromIntError>; if constexpr (MAX_PRIMITIVE < U::MAX_PRIMITIVE) { if (u.primitive_value > MAX_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(u32(static_cast<uint32_t>(u.primitive_value))); } template <UnsignedPrimitiveInteger U> __attribute__((pure)) constexpr ::sus::result::Result<u32, ::sus::num::TryFromIntError> u32::try_from(U u) noexcept { using R = ::sus::result::Result<u32, ::sus::num::TryFromIntError>; if constexpr (MAX_PRIMITIVE < __private::max_value<U>()) { if (u > MAX_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(u32(static_cast<uint32_t>(u))); } template <Signed S> __attribute__((pure)) constexpr ::sus::result::Result<u32, ::sus::num::TryFromIntError> u32::try_from(S s) noexcept { using R = ::sus::result::Result<u32, ::sus::num::TryFromIntError>; if (s.primitive_value < decltype(S::primitive_value){0}) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } constexpr auto umax = __private::into_unsigned(S::MAX_PRIMITIVE); if constexpr (MAX_PRIMITIVE < umax) { if (__private::into_unsigned(s.primitive_value) > MAX_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(u32(static_cast<uint32_t>(s.primitive_value))); } template <SignedPrimitiveInteger S> __attribute__((pure)) constexpr ::sus::result::Result<u32, ::sus::num::TryFromIntError> u32::try_from(S s) noexcept { using R = ::sus::result::Result<u32, ::sus::num::TryFromIntError>; if (s < 0) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } constexpr auto umax = __private::into_unsigned(__private::max_value<S>()); if constexpr (MAX_PRIMITIVE < umax) { if (__private::into_unsigned(s) > MAX_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(u32(static_cast<uint32_t>(s))); } template <class S> requires(SignedPrimitiveEnum<S> || SignedPrimitiveEnumClass<S>) __attribute__((pure)) constexpr ::sus::result::Result<u32, ::sus::num::TryFromIntError> u32::try_from(S s) noexcept { using D = std::underlying_type_t<S>; using R = ::sus::result::Result<u32, ::sus::num::TryFromIntError>; if (static_cast<D>(s) < 0) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } constexpr auto umax = __private::into_unsigned(__private::max_value<D>()); if constexpr (MAX_PRIMITIVE < umax) { if (__private::into_unsigned(static_cast<D>(s)) > MAX_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(u32(static_cast<uint32_t>(s))); } template <class U> requires(UnsignedPrimitiveEnum<U> || UnsignedPrimitiveEnumClass<U>) __attribute__((pure)) constexpr ::sus::result::Result<u32, ::sus::num::TryFromIntError> u32::try_from(U u) noexcept { using D = std::underlying_type_t<U>; using R = ::sus::result::Result<u32, ::sus::num::TryFromIntError>; if constexpr (MAX_PRIMITIVE < __private::max_value<D>()) { if (static_cast<D>(u) > MAX_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(u32(static_cast<uint32_t>(u))); } __attribute__((pure)) constexpr ::sus::option::Option<u32> u32::checked_add( const u32& rhs) const& noexcept { const auto out = __private::add_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return ::sus::option::Option<u32>::with(u32(out.value)); else return ::sus::option::Option<u32>(); } template <std::convertible_to<i32> S> __attribute__((pure)) constexpr ::sus::option::Option<u32> u32::checked_add_signed( const S& rhs) const& noexcept { const auto out = __private::add_with_overflow_signed(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return ::sus::option::Option<u32>::with(out.value); else return ::sus::option::Option<u32>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u32, bool> u32::overflowing_add( const u32& rhs) const& noexcept { const auto out = __private::add_with_overflow(primitive_value, rhs.primitive_value); return ::sus::tuple_type::Tuple<u32, bool>::with(u32(out.value), out.overflow); } template <std::convertible_to<i32> S> __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u32, bool> u32::overflowing_add_signed(const S& rhs) const& noexcept { const auto r = __private::add_with_overflow_signed(primitive_value, rhs.primitive_value); return ::sus::tuple_type::Tuple<u32, bool>::with(r.value, r.overflow); } __attribute__((pure)) constexpr ::sus::option::Option<u32> u32::checked_div( const u32& rhs) const& noexcept { if (rhs.primitive_value != 0u) [[likely]] return ::sus::option::Option<u32>::with( u32(__private::unchecked_div(primitive_value, rhs.primitive_value))); else return ::sus::option::Option<u32>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u32, bool> u32::overflowing_div( const u32& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return ::sus::tuple_type::Tuple<u32, bool>::with( u32(__private::unchecked_div(primitive_value, rhs.primitive_value)), false); } __attribute__((pure)) constexpr ::sus::option::Option<u32> u32::checked_mul( const u32& rhs) const& noexcept { const auto out = __private::mul_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return ::sus::option::Option<u32>::with(u32(out.value)); else return ::sus::option::Option<u32>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u32, bool> u32::overflowing_mul( const u32& rhs) const& noexcept { const auto out = __private::mul_with_overflow(primitive_value, rhs.primitive_value); return ::sus::tuple_type::Tuple<u32, bool>::with(u32(out.value), out.overflow); } __attribute__((pure)) constexpr ::sus::option::Option<u32> u32::checked_neg() const& noexcept { if (primitive_value == 0u) return ::sus::option::Option<u32>::with(u32(uint32_t{0u})); else return ::sus::option::Option<u32>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u32, bool> u32::overflowing_neg() const& noexcept { return ::sus::tuple_type::Tuple<u32, bool>::with( (~(*this)).wrapping_add(u32(uint32_t{1u})), primitive_value != 0u); } __attribute__((pure)) constexpr ::sus::option::Option<u32> u32::checked_rem( const u32& rhs) const& noexcept { if (rhs.primitive_value != 0u) [[likely]] return ::sus::option::Option<u32>::with( u32(__private::unchecked_rem(primitive_value, rhs.primitive_value))); else return ::sus::option::Option<u32>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u32, bool> u32::overflowing_rem( const u32& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return ::sus::tuple_type::Tuple<u32, bool>::with( u32(__private::unchecked_rem(primitive_value, rhs.primitive_value)), false); } __attribute__((pure)) constexpr ::sus::option::Option<u32> u32::checked_div_euclid( const u32& rhs) const& noexcept { if (rhs.primitive_value == 0u) [[unlikely]] { return ::sus::option::Option<u32>(); } else { return ::sus::option::Option<u32>::with( u32(__private::unchecked_div(primitive_value, rhs.primitive_value))); } } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u32, bool> u32::overflowing_div_euclid(const u32& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return ::sus::tuple_type::Tuple<u32, bool>::with( u32(__private::unchecked_div(primitive_value, rhs.primitive_value)), false); } __attribute__((pure)) constexpr ::sus::option::Option<u32> u32::checked_rem_euclid( const u32& rhs) const& noexcept { if (rhs.primitive_value == 0u) [[unlikely]] { return ::sus::option::Option<u32>(); } else { return ::sus::option::Option<u32>::with( u32(__private::unchecked_rem(primitive_value, rhs.primitive_value))); } } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u32, bool> u32::overflowing_rem_euclid(const u32& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return ::sus::tuple_type::Tuple<u32, bool>::with( u32(__private::unchecked_rem(primitive_value, rhs.primitive_value)), false); } __attribute__((pure)) constexpr ::sus::option::Option<u32> u32::checked_shl( const u32& rhs) const& noexcept { const auto out = __private::shl_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return ::sus::option::Option<u32>::with(u32(out.value)); else return ::sus::option::Option<u32>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u32, bool> u32::overflowing_shl( const u32& rhs) const& noexcept { const auto out = __private::shl_with_overflow(primitive_value, rhs.primitive_value); return ::sus::tuple_type::Tuple<u32, bool>::with(u32(out.value), out.overflow); } __attribute__((pure)) constexpr ::sus::option::Option<u32> u32::checked_shr( const u32& rhs) const& noexcept { const auto out = __private::shr_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return ::sus::option::Option<u32>::with(u32(out.value)); else return ::sus::option::Option<u32>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u32, bool> u32::overflowing_shr( const u32& rhs) const& noexcept { const auto out = __private::shr_with_overflow(primitive_value, rhs.primitive_value); return ::sus::tuple_type::Tuple<u32, bool>::with(u32(out.value), out.overflow); } __attribute__((pure)) constexpr ::sus::option::Option<u32> u32::checked_sub( const u32& rhs) const& { const auto out = __private::sub_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return ::sus::option::Option<u32>::with(u32(out.value)); else return ::sus::option::Option<u32>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u32, bool> u32::overflowing_sub( const u32& rhs) const& noexcept { const auto out = __private::sub_with_overflow(primitive_value, rhs.primitive_value); return ::sus::tuple_type::Tuple<u32, bool>::with(u32(out.value), out.overflow); } __attribute__((pure)) constexpr ::sus::option::Option<u32> u32::checked_pow( const u32& rhs) const& noexcept { const auto out = __private::pow_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return ::sus::option::Option<u32>::with(u32(out.value)); else return ::sus::option::Option<u32>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u32, bool> u32::overflowing_pow( const u32& exp) const& noexcept { const auto out = __private::pow_with_overflow(primitive_value, exp.primitive_value); return ::sus::tuple_type::Tuple<u32, bool>::with(u32(out.value), out.overflow); } __attribute__((pure)) constexpr ::sus::option::Option<u32> u32::checked_log2() const& noexcept { if (primitive_value == 0u) [[unlikely]] { return ::sus::option::Option<u32>(); } else { uint32_t zeros = __private::leading_zeros_nonzero(::sus::marker::unsafe_fn, primitive_value); return ::sus::option::Option<u32>::with(BITS - u32(1u) - u32(zeros)); } } __attribute__((pure)) constexpr u32 u32::log2() const& noexcept { return checked_log2().unwrap(); } __attribute__((pure)) constexpr ::sus::option::Option<u32> u32::checked_log10() const& noexcept { if (primitive_value == 0u) [[unlikely]] { return ::sus::option::Option<u32>(); } else { return ::sus::option::Option<u32>::with( __private::int_log10::u32(primitive_value)); } } __attribute__((pure)) constexpr u32 u32::log10() const& noexcept { return checked_log10().unwrap(); } __attribute__((pure)) constexpr ::sus::option::Option<u32> u32::checked_log( const u32& base) const& noexcept { if (primitive_value == 0u || base.primitive_value <= 1u) [[unlikely]] { return ::sus::option::Option<u32>(); } else { auto n = uint32_t{0u}; auto r = primitive_value; const auto b = base.primitive_value; while (r >= b) { r /= b; n += 1u; } return ::sus::option::Option<u32>::with(n); } } __attribute__((pure)) constexpr u32 u32::log(const u32& base) const& noexcept { return checked_log(base).unwrap(); } __attribute__((pure)) constexpr ::sus::option::Option<u32> u32::checked_next_power_of_two() const& noexcept { const auto one_less = __private::one_less_than_next_power_of_two(primitive_value); return u32(one_less).checked_add(u32(uint32_t{1u})); } __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<uint32_t>()> u32::to_be_bytes() const& noexcept { return to_be().to_ne_bytes(); } __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<uint32_t>()> u32::to_le_bytes() const& noexcept { return to_le().to_ne_bytes(); } __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<uint32_t>()> u32::to_ne_bytes() const& noexcept { auto bytes = ::sus::containers::Array<u8, ::sus::mem::size_of<uint32_t>()>(); if (std::is_constant_evaluated()) { auto uval = primitive_value; for (auto i = size_t{0}; i < ::sus::mem::size_of<uint32_t>(); ++i) { const auto last_byte = static_cast<uint8_t>(uval & 0xff); if (sus::assertions::is_little_endian()) bytes[i] = last_byte; else bytes[::sus::mem::size_of<uint32_t>() - 1 - i] = last_byte; if constexpr (::sus::mem::size_of<uint32_t>() > 1) uval >>= 8u; } return bytes; } else { ::sus::ptr::copy_nonoverlapping( ::sus::marker::unsafe_fn, reinterpret_cast<const char*>(&primitive_value), reinterpret_cast<char*>(bytes.as_mut_ptr()), ::sus::mem::size_of<uint32_t>()); return bytes; } } __attribute__((pure)) constexpr u32 u32::from_be_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<uint32_t>()>& bytes) noexcept { return from_be(from_ne_bytes(bytes)); } __attribute__((pure)) constexpr u32 u32::from_le_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<uint32_t>()>& bytes) noexcept { return from_le(from_ne_bytes(bytes)); } __attribute__((pure)) constexpr u32 u32::from_ne_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<uint32_t>()>& bytes) noexcept { uint32_t val; if (std::is_constant_evaluated()) { val = 0u; for (auto i = size_t{0}; i < ::sus::mem::size_of<uint32_t>(); ++i) { val |= bytes[i].primitive_value << (::sus::mem::size_of<uint32_t>() - 1 - i); } } else { ::sus::ptr::copy_nonoverlapping( ::sus::marker::unsafe_fn, reinterpret_cast<const char*>(bytes.as_ptr()), reinterpret_cast<char*>(&val), ::sus::mem::size_of<uint32_t>()); } return u32(val); } } template <> struct std::hash<::sus::num::u32> { __attribute__((pure)) auto operator()(::sus::num::u32 u) const noexcept { return std::hash<uint32_t>()(u.primitive_value); } }; template <> struct std::equal_to<::sus::num::u32> { __attribute__((pure)) constexpr auto operator()(::sus::num::u32 l, ::sus::num::u32 r) const noexcept { return l == r; } }; namespace sus::num { template <Unsigned U> __attribute__((pure)) constexpr ::sus::result::Result<u8, ::sus::num::TryFromIntError> u8::try_from(U u) noexcept { using R = ::sus::result::Result<u8, ::sus::num::TryFromIntError>; if constexpr (MAX_PRIMITIVE < U::MAX_PRIMITIVE) { if (u.primitive_value > MAX_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(u8(static_cast<uint8_t>(u.primitive_value))); } template <UnsignedPrimitiveInteger U> __attribute__((pure)) constexpr ::sus::result::Result<u8, ::sus::num::TryFromIntError> u8::try_from(U u) noexcept { using R = ::sus::result::Result<u8, ::sus::num::TryFromIntError>; if constexpr (MAX_PRIMITIVE < __private::max_value<U>()) { if (u > MAX_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(u8(static_cast<uint8_t>(u))); } template <Signed S> __attribute__((pure)) constexpr ::sus::result::Result<u8, ::sus::num::TryFromIntError> u8::try_from(S s) noexcept { using R = ::sus::result::Result<u8, ::sus::num::TryFromIntError>; if (s.primitive_value < decltype(S::primitive_value){0}) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } constexpr auto umax = __private::into_unsigned(S::MAX_PRIMITIVE); if constexpr (MAX_PRIMITIVE < umax) { if (__private::into_unsigned(s.primitive_value) > MAX_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(u8(static_cast<uint8_t>(s.primitive_value))); } template <SignedPrimitiveInteger S> __attribute__((pure)) constexpr ::sus::result::Result<u8, ::sus::num::TryFromIntError> u8::try_from(S s) noexcept { using R = ::sus::result::Result<u8, ::sus::num::TryFromIntError>; if (s < 0) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } constexpr auto umax = __private::into_unsigned(__private::max_value<S>()); if constexpr (MAX_PRIMITIVE < umax) { if (__private::into_unsigned(s) > MAX_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(u8(static_cast<uint8_t>(s))); } template <class S> requires(SignedPrimitiveEnum<S> || SignedPrimitiveEnumClass<S>) __attribute__((pure)) constexpr ::sus::result::Result<u8, ::sus::num::TryFromIntError> u8::try_from(S s) noexcept { using D = std::underlying_type_t<S>; using R = ::sus::result::Result<u8, ::sus::num::TryFromIntError>; if (static_cast<D>(s) < 0) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } constexpr auto umax = __private::into_unsigned(__private::max_value<D>()); if constexpr (MAX_PRIMITIVE < umax) { if (__private::into_unsigned(static_cast<D>(s)) > MAX_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(u8(static_cast<uint8_t>(s))); } template <class U> requires(UnsignedPrimitiveEnum<U> || UnsignedPrimitiveEnumClass<U>) __attribute__((pure)) constexpr ::sus::result::Result<u8, ::sus::num::TryFromIntError> u8::try_from(U u) noexcept { using D = std::underlying_type_t<U>; using R = ::sus::result::Result<u8, ::sus::num::TryFromIntError>; if constexpr (MAX_PRIMITIVE < __private::max_value<D>()) { if (static_cast<D>(u) > MAX_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(u8(static_cast<uint8_t>(u))); } __attribute__((pure)) constexpr ::sus::option::Option<u8> u8::checked_add( const u8& rhs) const& noexcept { const auto out = __private::add_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return ::sus::option::Option<u8>::with(u8(out.value)); else return ::sus::option::Option<u8>(); } template <std::convertible_to<i8> S> __attribute__((pure)) constexpr ::sus::option::Option<u8> u8::checked_add_signed( const S& rhs) const& noexcept { const auto out = __private::add_with_overflow_signed(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return ::sus::option::Option<u8>::with(out.value); else return ::sus::option::Option<u8>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u8, bool> u8::overflowing_add( const u8& rhs) const& noexcept { const auto out = __private::add_with_overflow(primitive_value, rhs.primitive_value); return ::sus::tuple_type::Tuple<u8, bool>::with(u8(out.value), out.overflow); } template <std::convertible_to<i8> S> __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u8, bool> u8::overflowing_add_signed(const S& rhs) const& noexcept { const auto r = __private::add_with_overflow_signed(primitive_value, rhs.primitive_value); return ::sus::tuple_type::Tuple<u8, bool>::with(r.value, r.overflow); } __attribute__((pure)) constexpr ::sus::option::Option<u8> u8::checked_div( const u8& rhs) const& noexcept { if (rhs.primitive_value != 0u) [[likely]] return ::sus::option::Option<u8>::with( u8(__private::unchecked_div(primitive_value, rhs.primitive_value))); else return ::sus::option::Option<u8>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u8, bool> u8::overflowing_div( const u8& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return ::sus::tuple_type::Tuple<u8, bool>::with( u8(__private::unchecked_div(primitive_value, rhs.primitive_value)), false); } __attribute__((pure)) constexpr ::sus::option::Option<u8> u8::checked_mul( const u8& rhs) const& noexcept { const auto out = __private::mul_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return ::sus::option::Option<u8>::with(u8(out.value)); else return ::sus::option::Option<u8>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u8, bool> u8::overflowing_mul( const u8& rhs) const& noexcept { const auto out = __private::mul_with_overflow(primitive_value, rhs.primitive_value); return ::sus::tuple_type::Tuple<u8, bool>::with(u8(out.value), out.overflow); } __attribute__((pure)) constexpr ::sus::option::Option<u8> u8::checked_neg() const& noexcept { if (primitive_value == 0u) return ::sus::option::Option<u8>::with(u8(uint8_t{0u})); else return ::sus::option::Option<u8>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u8, bool> u8::overflowing_neg() const& noexcept { return ::sus::tuple_type::Tuple<u8, bool>::with( (~(*this)).wrapping_add(u8(uint8_t{1u})), primitive_value != 0u); } __attribute__((pure)) constexpr ::sus::option::Option<u8> u8::checked_rem( const u8& rhs) const& noexcept { if (rhs.primitive_value != 0u) [[likely]] return ::sus::option::Option<u8>::with( u8(__private::unchecked_rem(primitive_value, rhs.primitive_value))); else return ::sus::option::Option<u8>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u8, bool> u8::overflowing_rem( const u8& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return ::sus::tuple_type::Tuple<u8, bool>::with( u8(__private::unchecked_rem(primitive_value, rhs.primitive_value)), false); } __attribute__((pure)) constexpr ::sus::option::Option<u8> u8::checked_div_euclid( const u8& rhs) const& noexcept { if (rhs.primitive_value == 0u) [[unlikely]] { return ::sus::option::Option<u8>(); } else { return ::sus::option::Option<u8>::with( u8(__private::unchecked_div(primitive_value, rhs.primitive_value))); } } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u8, bool> u8::overflowing_div_euclid(const u8& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return ::sus::tuple_type::Tuple<u8, bool>::with( u8(__private::unchecked_div(primitive_value, rhs.primitive_value)), false); } __attribute__((pure)) constexpr ::sus::option::Option<u8> u8::checked_rem_euclid( const u8& rhs) const& noexcept { if (rhs.primitive_value == 0u) [[unlikely]] { return ::sus::option::Option<u8>(); } else { return ::sus::option::Option<u8>::with( u8(__private::unchecked_rem(primitive_value, rhs.primitive_value))); } } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u8, bool> u8::overflowing_rem_euclid(const u8& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return ::sus::tuple_type::Tuple<u8, bool>::with( u8(__private::unchecked_rem(primitive_value, rhs.primitive_value)), false); } __attribute__((pure)) constexpr ::sus::option::Option<u8> u8::checked_shl( const u32& rhs) const& noexcept { const auto out = __private::shl_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return ::sus::option::Option<u8>::with(u8(out.value)); else return ::sus::option::Option<u8>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u8, bool> u8::overflowing_shl( const u32& rhs) const& noexcept { const auto out = __private::shl_with_overflow(primitive_value, rhs.primitive_value); return ::sus::tuple_type::Tuple<u8, bool>::with(u8(out.value), out.overflow); } __attribute__((pure)) constexpr ::sus::option::Option<u8> u8::checked_shr( const u32& rhs) const& noexcept { const auto out = __private::shr_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return ::sus::option::Option<u8>::with(u8(out.value)); else return ::sus::option::Option<u8>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u8, bool> u8::overflowing_shr( const u32& rhs) const& noexcept { const auto out = __private::shr_with_overflow(primitive_value, rhs.primitive_value); return ::sus::tuple_type::Tuple<u8, bool>::with(u8(out.value), out.overflow); } __attribute__((pure)) constexpr ::sus::option::Option<u8> u8::checked_sub( const u8& rhs) const& { const auto out = __private::sub_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return ::sus::option::Option<u8>::with(u8(out.value)); else return ::sus::option::Option<u8>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u8, bool> u8::overflowing_sub( const u8& rhs) const& noexcept { const auto out = __private::sub_with_overflow(primitive_value, rhs.primitive_value); return ::sus::tuple_type::Tuple<u8, bool>::with(u8(out.value), out.overflow); } __attribute__((pure)) constexpr ::sus::option::Option<u8> u8::checked_pow( const u32& rhs) const& noexcept { const auto out = __private::pow_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return ::sus::option::Option<u8>::with(u8(out.value)); else return ::sus::option::Option<u8>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u8, bool> u8::overflowing_pow( const u32& exp) const& noexcept { const auto out = __private::pow_with_overflow(primitive_value, exp.primitive_value); return ::sus::tuple_type::Tuple<u8, bool>::with(u8(out.value), out.overflow); } __attribute__((pure)) constexpr ::sus::option::Option<u32> u8::checked_log2() const& noexcept { if (primitive_value == 0u) [[unlikely]] { return ::sus::option::Option<u32>(); } else { uint32_t zeros = __private::leading_zeros_nonzero(::sus::marker::unsafe_fn, primitive_value); return ::sus::option::Option<u32>::with(BITS - u32(1u) - u32(zeros)); } } __attribute__((pure)) constexpr u32 u8::log2() const& noexcept { return checked_log2().unwrap(); } __attribute__((pure)) constexpr ::sus::option::Option<u32> u8::checked_log10() const& noexcept { if (primitive_value == 0u) [[unlikely]] { return ::sus::option::Option<u32>(); } else { return ::sus::option::Option<u32>::with( __private::int_log10::u8(primitive_value)); } } __attribute__((pure)) constexpr u32 u8::log10() const& noexcept { return checked_log10().unwrap(); } __attribute__((pure)) constexpr ::sus::option::Option<u32> u8::checked_log( const u8& base) const& noexcept { if (primitive_value == 0u || base.primitive_value <= 1u) [[unlikely]] { return ::sus::option::Option<u32>(); } else { auto n = uint32_t{0u}; auto r = primitive_value; const auto b = base.primitive_value; while (r >= b) { r /= b; n += 1u; } return ::sus::option::Option<u32>::with(n); } } __attribute__((pure)) constexpr u32 u8::log(const u8& base) const& noexcept { return checked_log(base).unwrap(); } __attribute__((pure)) constexpr ::sus::option::Option<u8> u8::checked_next_power_of_two() const& noexcept { const auto one_less = __private::one_less_than_next_power_of_two(primitive_value); return u8(one_less).checked_add(u8(uint8_t{1u})); } __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<uint8_t>()> u8::to_be_bytes() const& noexcept { return to_be().to_ne_bytes(); } __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<uint8_t>()> u8::to_le_bytes() const& noexcept { return to_le().to_ne_bytes(); } __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<uint8_t>()> u8::to_ne_bytes() const& noexcept { auto bytes = ::sus::containers::Array<u8, ::sus::mem::size_of<uint8_t>()>(); if (std::is_constant_evaluated()) { auto uval = primitive_value; for (auto i = size_t{0}; i < ::sus::mem::size_of<uint8_t>(); ++i) { const auto last_byte = static_cast<uint8_t>(uval & 0xff); if (sus::assertions::is_little_endian()) bytes[i] = last_byte; else bytes[::sus::mem::size_of<uint8_t>() - 1 - i] = last_byte; if constexpr (::sus::mem::size_of<uint8_t>() > 1) uval >>= 8u; } return bytes; } else { ::sus::ptr::copy_nonoverlapping( ::sus::marker::unsafe_fn, reinterpret_cast<const char*>(&primitive_value), reinterpret_cast<char*>(bytes.as_mut_ptr()), ::sus::mem::size_of<uint8_t>()); return bytes; } } __attribute__((pure)) constexpr u8 u8::from_be_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<uint8_t>()>& bytes) noexcept { return from_be(from_ne_bytes(bytes)); } __attribute__((pure)) constexpr u8 u8::from_le_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<uint8_t>()>& bytes) noexcept { return from_le(from_ne_bytes(bytes)); } __attribute__((pure)) constexpr u8 u8::from_ne_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<uint8_t>()>& bytes) noexcept { uint8_t val; if (std::is_constant_evaluated()) { val = 0u; for (auto i = size_t{0}; i < ::sus::mem::size_of<uint8_t>(); ++i) { val |= bytes[i].primitive_value << (::sus::mem::size_of<uint8_t>() - 1 - i); } } else { ::sus::ptr::copy_nonoverlapping( ::sus::marker::unsafe_fn, reinterpret_cast<const char*>(bytes.as_ptr()), reinterpret_cast<char*>(&val), ::sus::mem::size_of<uint8_t>()); } return u8(val); } } template <> struct std::hash<::sus::num::u8> { __attribute__((pure)) auto operator()(::sus::num::u8 u) const noexcept { return std::hash<uint8_t>()(u.primitive_value); } }; template <> struct std::equal_to<::sus::num::u8> { __attribute__((pure)) constexpr auto operator()(::sus::num::u8 l, ::sus::num::u8 r) const noexcept { return l == r; } }; namespace sus::num { template <Unsigned U> __attribute__((pure)) constexpr ::sus::result::Result<u16, ::sus::num::TryFromIntError> u16::try_from(U u) noexcept { using R = ::sus::result::Result<u16, ::sus::num::TryFromIntError>; if constexpr (MAX_PRIMITIVE < U::MAX_PRIMITIVE) { if (u.primitive_value > MAX_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(u16(static_cast<uint16_t>(u.primitive_value))); } template <UnsignedPrimitiveInteger U> __attribute__((pure)) constexpr ::sus::result::Result<u16, ::sus::num::TryFromIntError> u16::try_from(U u) noexcept { using R = ::sus::result::Result<u16, ::sus::num::TryFromIntError>; if constexpr (MAX_PRIMITIVE < __private::max_value<U>()) { if (u > MAX_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(u16(static_cast<uint16_t>(u))); } template <Signed S> __attribute__((pure)) constexpr ::sus::result::Result<u16, ::sus::num::TryFromIntError> u16::try_from(S s) noexcept { using R = ::sus::result::Result<u16, ::sus::num::TryFromIntError>; if (s.primitive_value < decltype(S::primitive_value){0}) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } constexpr auto umax = __private::into_unsigned(S::MAX_PRIMITIVE); if constexpr (MAX_PRIMITIVE < umax) { if (__private::into_unsigned(s.primitive_value) > MAX_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(u16(static_cast<uint16_t>(s.primitive_value))); } template <SignedPrimitiveInteger S> __attribute__((pure)) constexpr ::sus::result::Result<u16, ::sus::num::TryFromIntError> u16::try_from(S s) noexcept { using R = ::sus::result::Result<u16, ::sus::num::TryFromIntError>; if (s < 0) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } constexpr auto umax = __private::into_unsigned(__private::max_value<S>()); if constexpr (MAX_PRIMITIVE < umax) { if (__private::into_unsigned(s) > MAX_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(u16(static_cast<uint16_t>(s))); } template <class S> requires(SignedPrimitiveEnum<S> || SignedPrimitiveEnumClass<S>) __attribute__((pure)) constexpr ::sus::result::Result<u16, ::sus::num::TryFromIntError> u16::try_from(S s) noexcept { using D = std::underlying_type_t<S>; using R = ::sus::result::Result<u16, ::sus::num::TryFromIntError>; if (static_cast<D>(s) < 0) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } constexpr auto umax = __private::into_unsigned(__private::max_value<D>()); if constexpr (MAX_PRIMITIVE < umax) { if (__private::into_unsigned(static_cast<D>(s)) > MAX_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(u16(static_cast<uint16_t>(s))); } template <class U> requires(UnsignedPrimitiveEnum<U> || UnsignedPrimitiveEnumClass<U>) __attribute__((pure)) constexpr ::sus::result::Result<u16, ::sus::num::TryFromIntError> u16::try_from(U u) noexcept { using D = std::underlying_type_t<U>; using R = ::sus::result::Result<u16, ::sus::num::TryFromIntError>; if constexpr (MAX_PRIMITIVE < __private::max_value<D>()) { if (static_cast<D>(u) > MAX_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(u16(static_cast<uint16_t>(u))); } __attribute__((pure)) constexpr ::sus::option::Option<u16> u16::checked_add( const u16& rhs) const& noexcept { const auto out = __private::add_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return ::sus::option::Option<u16>::with(u16(out.value)); else return ::sus::option::Option<u16>(); } template <std::convertible_to<i16> S> __attribute__((pure)) constexpr ::sus::option::Option<u16> u16::checked_add_signed( const S& rhs) const& noexcept { const auto out = __private::add_with_overflow_signed(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return ::sus::option::Option<u16>::with(out.value); else return ::sus::option::Option<u16>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u16, bool> u16::overflowing_add( const u16& rhs) const& noexcept { const auto out = __private::add_with_overflow(primitive_value, rhs.primitive_value); return ::sus::tuple_type::Tuple<u16, bool>::with(u16(out.value), out.overflow); } template <std::convertible_to<i16> S> __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u16, bool> u16::overflowing_add_signed(const S& rhs) const& noexcept { const auto r = __private::add_with_overflow_signed(primitive_value, rhs.primitive_value); return ::sus::tuple_type::Tuple<u16, bool>::with(r.value, r.overflow); } __attribute__((pure)) constexpr ::sus::option::Option<u16> u16::checked_div( const u16& rhs) const& noexcept { if (rhs.primitive_value != 0u) [[likely]] return ::sus::option::Option<u16>::with( u16(__private::unchecked_div(primitive_value, rhs.primitive_value))); else return ::sus::option::Option<u16>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u16, bool> u16::overflowing_div( const u16& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return ::sus::tuple_type::Tuple<u16, bool>::with( u16(__private::unchecked_div(primitive_value, rhs.primitive_value)), false); } __attribute__((pure)) constexpr ::sus::option::Option<u16> u16::checked_mul( const u16& rhs) const& noexcept { const auto out = __private::mul_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return ::sus::option::Option<u16>::with(u16(out.value)); else return ::sus::option::Option<u16>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u16, bool> u16::overflowing_mul( const u16& rhs) const& noexcept { const auto out = __private::mul_with_overflow(primitive_value, rhs.primitive_value); return ::sus::tuple_type::Tuple<u16, bool>::with(u16(out.value), out.overflow); } __attribute__((pure)) constexpr ::sus::option::Option<u16> u16::checked_neg() const& noexcept { if (primitive_value == 0u) return ::sus::option::Option<u16>::with(u16(uint16_t{0u})); else return ::sus::option::Option<u16>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u16, bool> u16::overflowing_neg() const& noexcept { return ::sus::tuple_type::Tuple<u16, bool>::with( (~(*this)).wrapping_add(u16(uint16_t{1u})), primitive_value != 0u); } __attribute__((pure)) constexpr ::sus::option::Option<u16> u16::checked_rem( const u16& rhs) const& noexcept { if (rhs.primitive_value != 0u) [[likely]] return ::sus::option::Option<u16>::with( u16(__private::unchecked_rem(primitive_value, rhs.primitive_value))); else return ::sus::option::Option<u16>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u16, bool> u16::overflowing_rem( const u16& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return ::sus::tuple_type::Tuple<u16, bool>::with( u16(__private::unchecked_rem(primitive_value, rhs.primitive_value)), false); } __attribute__((pure)) constexpr ::sus::option::Option<u16> u16::checked_div_euclid( const u16& rhs) const& noexcept { if (rhs.primitive_value == 0u) [[unlikely]] { return ::sus::option::Option<u16>(); } else { return ::sus::option::Option<u16>::with( u16(__private::unchecked_div(primitive_value, rhs.primitive_value))); } } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u16, bool> u16::overflowing_div_euclid(const u16& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return ::sus::tuple_type::Tuple<u16, bool>::with( u16(__private::unchecked_div(primitive_value, rhs.primitive_value)), false); } __attribute__((pure)) constexpr ::sus::option::Option<u16> u16::checked_rem_euclid( const u16& rhs) const& noexcept { if (rhs.primitive_value == 0u) [[unlikely]] { return ::sus::option::Option<u16>(); } else { return ::sus::option::Option<u16>::with( u16(__private::unchecked_rem(primitive_value, rhs.primitive_value))); } } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u16, bool> u16::overflowing_rem_euclid(const u16& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return ::sus::tuple_type::Tuple<u16, bool>::with( u16(__private::unchecked_rem(primitive_value, rhs.primitive_value)), false); } __attribute__((pure)) constexpr ::sus::option::Option<u16> u16::checked_shl( const u32& rhs) const& noexcept { const auto out = __private::shl_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return ::sus::option::Option<u16>::with(u16(out.value)); else return ::sus::option::Option<u16>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u16, bool> u16::overflowing_shl( const u32& rhs) const& noexcept { const auto out = __private::shl_with_overflow(primitive_value, rhs.primitive_value); return ::sus::tuple_type::Tuple<u16, bool>::with(u16(out.value), out.overflow); } __attribute__((pure)) constexpr ::sus::option::Option<u16> u16::checked_shr( const u32& rhs) const& noexcept { const auto out = __private::shr_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return ::sus::option::Option<u16>::with(u16(out.value)); else return ::sus::option::Option<u16>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u16, bool> u16::overflowing_shr( const u32& rhs) const& noexcept { const auto out = __private::shr_with_overflow(primitive_value, rhs.primitive_value); return ::sus::tuple_type::Tuple<u16, bool>::with(u16(out.value), out.overflow); } __attribute__((pure)) constexpr ::sus::option::Option<u16> u16::checked_sub( const u16& rhs) const& { const auto out = __private::sub_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return ::sus::option::Option<u16>::with(u16(out.value)); else return ::sus::option::Option<u16>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u16, bool> u16::overflowing_sub( const u16& rhs) const& noexcept { const auto out = __private::sub_with_overflow(primitive_value, rhs.primitive_value); return ::sus::tuple_type::Tuple<u16, bool>::with(u16(out.value), out.overflow); } __attribute__((pure)) constexpr ::sus::option::Option<u16> u16::checked_pow( const u32& rhs) const& noexcept { const auto out = __private::pow_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return ::sus::option::Option<u16>::with(u16(out.value)); else return ::sus::option::Option<u16>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u16, bool> u16::overflowing_pow( const u32& exp) const& noexcept { const auto out = __private::pow_with_overflow(primitive_value, exp.primitive_value); return ::sus::tuple_type::Tuple<u16, bool>::with(u16(out.value), out.overflow); } __attribute__((pure)) constexpr ::sus::option::Option<u32> u16::checked_log2() const& noexcept { if (primitive_value == 0u) [[unlikely]] { return ::sus::option::Option<u32>(); } else { uint32_t zeros = __private::leading_zeros_nonzero(::sus::marker::unsafe_fn, primitive_value); return ::sus::option::Option<u32>::with(BITS - u32(1u) - u32(zeros)); } } __attribute__((pure)) constexpr u32 u16::log2() const& noexcept { return checked_log2().unwrap(); } __attribute__((pure)) constexpr ::sus::option::Option<u32> u16::checked_log10() const& noexcept { if (primitive_value == 0u) [[unlikely]] { return ::sus::option::Option<u32>(); } else { return ::sus::option::Option<u32>::with( __private::int_log10::u16(primitive_value)); } } __attribute__((pure)) constexpr u32 u16::log10() const& noexcept { return checked_log10().unwrap(); } __attribute__((pure)) constexpr ::sus::option::Option<u32> u16::checked_log( const u16& base) const& noexcept { if (primitive_value == 0u || base.primitive_value <= 1u) [[unlikely]] { return ::sus::option::Option<u32>(); } else { auto n = uint32_t{0u}; auto r = primitive_value; const auto b = base.primitive_value; while (r >= b) { r /= b; n += 1u; } return ::sus::option::Option<u32>::with(n); } } __attribute__((pure)) constexpr u32 u16::log(const u16& base) const& noexcept { return checked_log(base).unwrap(); } __attribute__((pure)) constexpr ::sus::option::Option<u16> u16::checked_next_power_of_two() const& noexcept { const auto one_less = __private::one_less_than_next_power_of_two(primitive_value); return u16(one_less).checked_add(u16(uint16_t{1u})); } __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<uint16_t>()> u16::to_be_bytes() const& noexcept { return to_be().to_ne_bytes(); } __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<uint16_t>()> u16::to_le_bytes() const& noexcept { return to_le().to_ne_bytes(); } __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<uint16_t>()> u16::to_ne_bytes() const& noexcept { auto bytes = ::sus::containers::Array<u8, ::sus::mem::size_of<uint16_t>()>(); if (std::is_constant_evaluated()) { auto uval = primitive_value; for (auto i = size_t{0}; i < ::sus::mem::size_of<uint16_t>(); ++i) { const auto last_byte = static_cast<uint8_t>(uval & 0xff); if (sus::assertions::is_little_endian()) bytes[i] = last_byte; else bytes[::sus::mem::size_of<uint16_t>() - 1 - i] = last_byte; if constexpr (::sus::mem::size_of<uint16_t>() > 1) uval >>= 8u; } return bytes; } else { ::sus::ptr::copy_nonoverlapping( ::sus::marker::unsafe_fn, reinterpret_cast<const char*>(&primitive_value), reinterpret_cast<char*>(bytes.as_mut_ptr()), ::sus::mem::size_of<uint16_t>()); return bytes; } } __attribute__((pure)) constexpr u16 u16::from_be_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<uint16_t>()>& bytes) noexcept { return from_be(from_ne_bytes(bytes)); } __attribute__((pure)) constexpr u16 u16::from_le_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<uint16_t>()>& bytes) noexcept { return from_le(from_ne_bytes(bytes)); } __attribute__((pure)) constexpr u16 u16::from_ne_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<uint16_t>()>& bytes) noexcept { uint16_t val; if (std::is_constant_evaluated()) { val = 0u; for (auto i = size_t{0}; i < ::sus::mem::size_of<uint16_t>(); ++i) { val |= bytes[i].primitive_value << (::sus::mem::size_of<uint16_t>() - 1 - i); } } else { ::sus::ptr::copy_nonoverlapping( ::sus::marker::unsafe_fn, reinterpret_cast<const char*>(bytes.as_ptr()), reinterpret_cast<char*>(&val), ::sus::mem::size_of<uint16_t>()); } return u16(val); } } template <> struct std::hash<::sus::num::u16> { __attribute__((pure)) auto operator()(::sus::num::u16 u) const noexcept { return std::hash<uint16_t>()(u.primitive_value); } }; template <> struct std::equal_to<::sus::num::u16> { __attribute__((pure)) constexpr auto operator()(::sus::num::u16 l, ::sus::num::u16 r) const noexcept { return l == r; } }; namespace sus::num { template <Unsigned U> __attribute__((pure)) constexpr ::sus::result::Result<u64, ::sus::num::TryFromIntError> u64::try_from(U u) noexcept { using R = ::sus::result::Result<u64, ::sus::num::TryFromIntError>; if constexpr (MAX_PRIMITIVE < U::MAX_PRIMITIVE) { if (u.primitive_value > MAX_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(u64(static_cast<uint64_t>(u.primitive_value))); } template <UnsignedPrimitiveInteger U> __attribute__((pure)) constexpr ::sus::result::Result<u64, ::sus::num::TryFromIntError> u64::try_from(U u) noexcept { using R = ::sus::result::Result<u64, ::sus::num::TryFromIntError>; if constexpr (MAX_PRIMITIVE < __private::max_value<U>()) { if (u > MAX_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(u64(static_cast<uint64_t>(u))); } template <Signed S> __attribute__((pure)) constexpr ::sus::result::Result<u64, ::sus::num::TryFromIntError> u64::try_from(S s) noexcept { using R = ::sus::result::Result<u64, ::sus::num::TryFromIntError>; if (s.primitive_value < decltype(S::primitive_value){0}) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } constexpr auto umax = __private::into_unsigned(S::MAX_PRIMITIVE); if constexpr (MAX_PRIMITIVE < umax) { if (__private::into_unsigned(s.primitive_value) > MAX_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(u64(static_cast<uint64_t>(s.primitive_value))); } template <SignedPrimitiveInteger S> __attribute__((pure)) constexpr ::sus::result::Result<u64, ::sus::num::TryFromIntError> u64::try_from(S s) noexcept { using R = ::sus::result::Result<u64, ::sus::num::TryFromIntError>; if (s < 0) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } constexpr auto umax = __private::into_unsigned(__private::max_value<S>()); if constexpr (MAX_PRIMITIVE < umax) { if (__private::into_unsigned(s) > MAX_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(u64(static_cast<uint64_t>(s))); } template <class S> requires(SignedPrimitiveEnum<S> || SignedPrimitiveEnumClass<S>) __attribute__((pure)) constexpr ::sus::result::Result<u64, ::sus::num::TryFromIntError> u64::try_from(S s) noexcept { using D = std::underlying_type_t<S>; using R = ::sus::result::Result<u64, ::sus::num::TryFromIntError>; if (static_cast<D>(s) < 0) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } constexpr auto umax = __private::into_unsigned(__private::max_value<D>()); if constexpr (MAX_PRIMITIVE < umax) { if (__private::into_unsigned(static_cast<D>(s)) > MAX_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(u64(static_cast<uint64_t>(s))); } template <class U> requires(UnsignedPrimitiveEnum<U> || UnsignedPrimitiveEnumClass<U>) __attribute__((pure)) constexpr ::sus::result::Result<u64, ::sus::num::TryFromIntError> u64::try_from(U u) noexcept { using D = std::underlying_type_t<U>; using R = ::sus::result::Result<u64, ::sus::num::TryFromIntError>; if constexpr (MAX_PRIMITIVE < __private::max_value<D>()) { if (static_cast<D>(u) > MAX_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(u64(static_cast<uint64_t>(u))); } __attribute__((pure)) constexpr ::sus::option::Option<u64> u64::checked_add( const u64& rhs) const& noexcept { const auto out = __private::add_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return ::sus::option::Option<u64>::with(u64(out.value)); else return ::sus::option::Option<u64>(); } template <std::convertible_to<i64> S> __attribute__((pure)) constexpr ::sus::option::Option<u64> u64::checked_add_signed( const S& rhs) const& noexcept { const auto out = __private::add_with_overflow_signed(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return ::sus::option::Option<u64>::with(out.value); else return ::sus::option::Option<u64>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u64, bool> u64::overflowing_add( const u64& rhs) const& noexcept { const auto out = __private::add_with_overflow(primitive_value, rhs.primitive_value); return ::sus::tuple_type::Tuple<u64, bool>::with(u64(out.value), out.overflow); } template <std::convertible_to<i64> S> __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u64, bool> u64::overflowing_add_signed(const S& rhs) const& noexcept { const auto r = __private::add_with_overflow_signed(primitive_value, rhs.primitive_value); return ::sus::tuple_type::Tuple<u64, bool>::with(r.value, r.overflow); } __attribute__((pure)) constexpr ::sus::option::Option<u64> u64::checked_div( const u64& rhs) const& noexcept { if (rhs.primitive_value != 0u) [[likely]] return ::sus::option::Option<u64>::with( u64(__private::unchecked_div(primitive_value, rhs.primitive_value))); else return ::sus::option::Option<u64>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u64, bool> u64::overflowing_div( const u64& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return ::sus::tuple_type::Tuple<u64, bool>::with( u64(__private::unchecked_div(primitive_value, rhs.primitive_value)), false); } __attribute__((pure)) constexpr ::sus::option::Option<u64> u64::checked_mul( const u64& rhs) const& noexcept { const auto out = __private::mul_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return ::sus::option::Option<u64>::with(u64(out.value)); else return ::sus::option::Option<u64>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u64, bool> u64::overflowing_mul( const u64& rhs) const& noexcept { const auto out = __private::mul_with_overflow(primitive_value, rhs.primitive_value); return ::sus::tuple_type::Tuple<u64, bool>::with(u64(out.value), out.overflow); } __attribute__((pure)) constexpr ::sus::option::Option<u64> u64::checked_neg() const& noexcept { if (primitive_value == 0u) return ::sus::option::Option<u64>::with(u64(uint64_t{0u})); else return ::sus::option::Option<u64>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u64, bool> u64::overflowing_neg() const& noexcept { return ::sus::tuple_type::Tuple<u64, bool>::with( (~(*this)).wrapping_add(u64(uint64_t{1u})), primitive_value != 0u); } __attribute__((pure)) constexpr ::sus::option::Option<u64> u64::checked_rem( const u64& rhs) const& noexcept { if (rhs.primitive_value != 0u) [[likely]] return ::sus::option::Option<u64>::with( u64(__private::unchecked_rem(primitive_value, rhs.primitive_value))); else return ::sus::option::Option<u64>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u64, bool> u64::overflowing_rem( const u64& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return ::sus::tuple_type::Tuple<u64, bool>::with( u64(__private::unchecked_rem(primitive_value, rhs.primitive_value)), false); } __attribute__((pure)) constexpr ::sus::option::Option<u64> u64::checked_div_euclid( const u64& rhs) const& noexcept { if (rhs.primitive_value == 0u) [[unlikely]] { return ::sus::option::Option<u64>(); } else { return ::sus::option::Option<u64>::with( u64(__private::unchecked_div(primitive_value, rhs.primitive_value))); } } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u64, bool> u64::overflowing_div_euclid(const u64& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return ::sus::tuple_type::Tuple<u64, bool>::with( u64(__private::unchecked_div(primitive_value, rhs.primitive_value)), false); } __attribute__((pure)) constexpr ::sus::option::Option<u64> u64::checked_rem_euclid( const u64& rhs) const& noexcept { if (rhs.primitive_value == 0u) [[unlikely]] { return ::sus::option::Option<u64>(); } else { return ::sus::option::Option<u64>::with( u64(__private::unchecked_rem(primitive_value, rhs.primitive_value))); } } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u64, bool> u64::overflowing_rem_euclid(const u64& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return ::sus::tuple_type::Tuple<u64, bool>::with( u64(__private::unchecked_rem(primitive_value, rhs.primitive_value)), false); } __attribute__((pure)) constexpr ::sus::option::Option<u64> u64::checked_shl( const u32& rhs) const& noexcept { const auto out = __private::shl_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return ::sus::option::Option<u64>::with(u64(out.value)); else return ::sus::option::Option<u64>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u64, bool> u64::overflowing_shl( const u32& rhs) const& noexcept { const auto out = __private::shl_with_overflow(primitive_value, rhs.primitive_value); return ::sus::tuple_type::Tuple<u64, bool>::with(u64(out.value), out.overflow); } __attribute__((pure)) constexpr ::sus::option::Option<u64> u64::checked_shr( const u32& rhs) const& noexcept { const auto out = __private::shr_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return ::sus::option::Option<u64>::with(u64(out.value)); else return ::sus::option::Option<u64>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u64, bool> u64::overflowing_shr( const u32& rhs) const& noexcept { const auto out = __private::shr_with_overflow(primitive_value, rhs.primitive_value); return ::sus::tuple_type::Tuple<u64, bool>::with(u64(out.value), out.overflow); } __attribute__((pure)) constexpr ::sus::option::Option<u64> u64::checked_sub( const u64& rhs) const& { const auto out = __private::sub_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return ::sus::option::Option<u64>::with(u64(out.value)); else return ::sus::option::Option<u64>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u64, bool> u64::overflowing_sub( const u64& rhs) const& noexcept { const auto out = __private::sub_with_overflow(primitive_value, rhs.primitive_value); return ::sus::tuple_type::Tuple<u64, bool>::with(u64(out.value), out.overflow); } __attribute__((pure)) constexpr ::sus::option::Option<u64> u64::checked_pow( const u32& rhs) const& noexcept { const auto out = __private::pow_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return ::sus::option::Option<u64>::with(u64(out.value)); else return ::sus::option::Option<u64>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<u64, bool> u64::overflowing_pow( const u32& exp) const& noexcept { const auto out = __private::pow_with_overflow(primitive_value, exp.primitive_value); return ::sus::tuple_type::Tuple<u64, bool>::with(u64(out.value), out.overflow); } __attribute__((pure)) constexpr ::sus::option::Option<u32> u64::checked_log2() const& noexcept { if (primitive_value == 0u) [[unlikely]] { return ::sus::option::Option<u32>(); } else { uint32_t zeros = __private::leading_zeros_nonzero(::sus::marker::unsafe_fn, primitive_value); return ::sus::option::Option<u32>::with(BITS - u32(1u) - u32(zeros)); } } __attribute__((pure)) constexpr u32 u64::log2() const& noexcept { return checked_log2().unwrap(); } __attribute__((pure)) constexpr ::sus::option::Option<u32> u64::checked_log10() const& noexcept { if (primitive_value == 0u) [[unlikely]] { return ::sus::option::Option<u32>(); } else { return ::sus::option::Option<u32>::with( __private::int_log10::u64(primitive_value)); } } __attribute__((pure)) constexpr u32 u64::log10() const& noexcept { return checked_log10().unwrap(); } __attribute__((pure)) constexpr ::sus::option::Option<u32> u64::checked_log( const u64& base) const& noexcept { if (primitive_value == 0u || base.primitive_value <= 1u) [[unlikely]] { return ::sus::option::Option<u32>(); } else { auto n = uint32_t{0u}; auto r = primitive_value; const auto b = base.primitive_value; while (r >= b) { r /= b; n += 1u; } return ::sus::option::Option<u32>::with(n); } } __attribute__((pure)) constexpr u32 u64::log(const u64& base) const& noexcept { return checked_log(base).unwrap(); } __attribute__((pure)) constexpr ::sus::option::Option<u64> u64::checked_next_power_of_two() const& noexcept { const auto one_less = __private::one_less_than_next_power_of_two(primitive_value); return u64(one_less).checked_add(u64(uint64_t{1u})); } __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<uint64_t>()> u64::to_be_bytes() const& noexcept { return to_be().to_ne_bytes(); } __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<uint64_t>()> u64::to_le_bytes() const& noexcept { return to_le().to_ne_bytes(); } __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<uint64_t>()> u64::to_ne_bytes() const& noexcept { auto bytes = ::sus::containers::Array<u8, ::sus::mem::size_of<uint64_t>()>(); if (std::is_constant_evaluated()) { auto uval = primitive_value; for (auto i = size_t{0}; i < ::sus::mem::size_of<uint64_t>(); ++i) { const auto last_byte = static_cast<uint8_t>(uval & 0xff); if (sus::assertions::is_little_endian()) bytes[i] = last_byte; else bytes[::sus::mem::size_of<uint64_t>() - 1 - i] = last_byte; if constexpr (::sus::mem::size_of<uint64_t>() > 1) uval >>= 8u; } return bytes; } else { ::sus::ptr::copy_nonoverlapping( ::sus::marker::unsafe_fn, reinterpret_cast<const char*>(&primitive_value), reinterpret_cast<char*>(bytes.as_mut_ptr()), ::sus::mem::size_of<uint64_t>()); return bytes; } } __attribute__((pure)) constexpr u64 u64::from_be_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<uint64_t>()>& bytes) noexcept { return from_be(from_ne_bytes(bytes)); } __attribute__((pure)) constexpr u64 u64::from_le_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<uint64_t>()>& bytes) noexcept { return from_le(from_ne_bytes(bytes)); } __attribute__((pure)) constexpr u64 u64::from_ne_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<uint64_t>()>& bytes) noexcept { uint64_t val; if (std::is_constant_evaluated()) { val = 0u; for (auto i = size_t{0}; i < ::sus::mem::size_of<uint64_t>(); ++i) { val |= bytes[i].primitive_value << (::sus::mem::size_of<uint64_t>() - 1 - i); } } else { ::sus::ptr::copy_nonoverlapping( ::sus::marker::unsafe_fn, reinterpret_cast<const char*>(bytes.as_ptr()), reinterpret_cast<char*>(&val), ::sus::mem::size_of<uint64_t>()); } return u64(val); } } template <> struct std::hash<::sus::num::u64> { __attribute__((pure)) auto operator()(::sus::num::u64 u) const noexcept { return std::hash<uint64_t>()(u.primitive_value); } }; template <> struct std::equal_to<::sus::num::u64> { __attribute__((pure)) constexpr auto operator()(::sus::num::u64 l, ::sus::num::u64 r) const noexcept { return l == r; } }; namespace sus::num { template <Unsigned U> __attribute__((pure)) constexpr ::sus::result::Result<usize, ::sus::num::TryFromIntError> usize::try_from(U u) noexcept { using R = ::sus::result::Result<usize, ::sus::num::TryFromIntError>; if constexpr (MAX_PRIMITIVE < U::MAX_PRIMITIVE) { if (u.primitive_value > MAX_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(usize(static_cast< ::sus::num::__private::addr_type<>::unsigned_type>(u.primitive_value))); } template <UnsignedPrimitiveInteger U> __attribute__((pure)) constexpr ::sus::result::Result<usize, ::sus::num::TryFromIntError> usize::try_from(U u) noexcept { using R = ::sus::result::Result<usize, ::sus::num::TryFromIntError>; if constexpr (MAX_PRIMITIVE < __private::max_value<U>()) { if (u > MAX_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(usize(static_cast< ::sus::num::__private::addr_type<>::unsigned_type>(u))); } template <Signed S> __attribute__((pure)) constexpr ::sus::result::Result<usize, ::sus::num::TryFromIntError> usize::try_from(S s) noexcept { using R = ::sus::result::Result<usize, ::sus::num::TryFromIntError>; if (s.primitive_value < decltype(S::primitive_value){0}) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } constexpr auto umax = __private::into_unsigned(S::MAX_PRIMITIVE); if constexpr (MAX_PRIMITIVE < umax) { if (__private::into_unsigned(s.primitive_value) > MAX_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(usize(static_cast< ::sus::num::__private::addr_type<>::unsigned_type>(s.primitive_value))); } template <SignedPrimitiveInteger S> __attribute__((pure)) constexpr ::sus::result::Result<usize, ::sus::num::TryFromIntError> usize::try_from(S s) noexcept { using R = ::sus::result::Result<usize, ::sus::num::TryFromIntError>; if (s < 0) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } constexpr auto umax = __private::into_unsigned(__private::max_value<S>()); if constexpr (MAX_PRIMITIVE < umax) { if (__private::into_unsigned(s) > MAX_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(usize(static_cast< ::sus::num::__private::addr_type<>::unsigned_type>(s))); } template <class S> requires(SignedPrimitiveEnum<S> || SignedPrimitiveEnumClass<S>) __attribute__((pure)) constexpr ::sus::result::Result<usize, ::sus::num::TryFromIntError> usize::try_from(S s) noexcept { using D = std::underlying_type_t<S>; using R = ::sus::result::Result<usize, ::sus::num::TryFromIntError>; if (static_cast<D>(s) < 0) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } constexpr auto umax = __private::into_unsigned(__private::max_value<D>()); if constexpr (MAX_PRIMITIVE < umax) { if (__private::into_unsigned(static_cast<D>(s)) > MAX_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(usize(static_cast< ::sus::num::__private::addr_type<>::unsigned_type>(s))); } template <class U> requires(UnsignedPrimitiveEnum<U> || UnsignedPrimitiveEnumClass<U>) __attribute__((pure)) constexpr ::sus::result::Result<usize, ::sus::num::TryFromIntError> usize::try_from(U u) noexcept { using D = std::underlying_type_t<U>; using R = ::sus::result::Result<usize, ::sus::num::TryFromIntError>; if constexpr (MAX_PRIMITIVE < __private::max_value<D>()) { if (static_cast<D>(u) > MAX_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(usize(static_cast< ::sus::num::__private::addr_type<>::unsigned_type>(u))); } __attribute__((pure)) constexpr ::sus::option::Option<usize> usize::checked_add( const usize& rhs) const& noexcept { const auto out = __private::add_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return ::sus::option::Option<usize>::with(usize(out.value)); else return ::sus::option::Option<usize>(); } template <std::convertible_to<isize> S> __attribute__((pure)) constexpr ::sus::option::Option<usize> usize::checked_add_signed( const S& rhs) const& noexcept { const auto out = __private::add_with_overflow_signed(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return ::sus::option::Option<usize>::with(out.value); else return ::sus::option::Option<usize>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<usize, bool> usize::overflowing_add( const usize& rhs) const& noexcept { const auto out = __private::add_with_overflow(primitive_value, rhs.primitive_value); return ::sus::tuple_type::Tuple<usize, bool>::with(usize(out.value), out.overflow); } template <std::convertible_to<isize> S> __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<usize, bool> usize::overflowing_add_signed(const S& rhs) const& noexcept { const auto r = __private::add_with_overflow_signed(primitive_value, rhs.primitive_value); return ::sus::tuple_type::Tuple<usize, bool>::with(r.value, r.overflow); } __attribute__((pure)) constexpr ::sus::option::Option<usize> usize::checked_div( const usize& rhs) const& noexcept { if (rhs.primitive_value != 0u) [[likely]] return ::sus::option::Option<usize>::with( usize(__private::unchecked_div(primitive_value, rhs.primitive_value))); else return ::sus::option::Option<usize>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<usize, bool> usize::overflowing_div( const usize& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return ::sus::tuple_type::Tuple<usize, bool>::with( usize(__private::unchecked_div(primitive_value, rhs.primitive_value)), false); } __attribute__((pure)) constexpr ::sus::option::Option<usize> usize::checked_mul( const usize& rhs) const& noexcept { const auto out = __private::mul_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return ::sus::option::Option<usize>::with(usize(out.value)); else return ::sus::option::Option<usize>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<usize, bool> usize::overflowing_mul( const usize& rhs) const& noexcept { const auto out = __private::mul_with_overflow(primitive_value, rhs.primitive_value); return ::sus::tuple_type::Tuple<usize, bool>::with(usize(out.value), out.overflow); } __attribute__((pure)) constexpr ::sus::option::Option<usize> usize::checked_neg() const& noexcept { if (primitive_value == 0u) return ::sus::option::Option<usize>::with(usize(::sus::num::__private::addr_type<>::unsigned_type{0u})); else return ::sus::option::Option<usize>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<usize, bool> usize::overflowing_neg() const& noexcept { return ::sus::tuple_type::Tuple<usize, bool>::with( (~(*this)).wrapping_add(usize(::sus::num::__private::addr_type<>::unsigned_type{1u})), primitive_value != 0u); } __attribute__((pure)) constexpr ::sus::option::Option<usize> usize::checked_rem( const usize& rhs) const& noexcept { if (rhs.primitive_value != 0u) [[likely]] return ::sus::option::Option<usize>::with( usize(__private::unchecked_rem(primitive_value, rhs.primitive_value))); else return ::sus::option::Option<usize>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<usize, bool> usize::overflowing_rem( const usize& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return ::sus::tuple_type::Tuple<usize, bool>::with( usize(__private::unchecked_rem(primitive_value, rhs.primitive_value)), false); } __attribute__((pure)) constexpr ::sus::option::Option<usize> usize::checked_div_euclid( const usize& rhs) const& noexcept { if (rhs.primitive_value == 0u) [[unlikely]] { return ::sus::option::Option<usize>(); } else { return ::sus::option::Option<usize>::with( usize(__private::unchecked_div(primitive_value, rhs.primitive_value))); } } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<usize, bool> usize::overflowing_div_euclid(const usize& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return ::sus::tuple_type::Tuple<usize, bool>::with( usize(__private::unchecked_div(primitive_value, rhs.primitive_value)), false); } __attribute__((pure)) constexpr ::sus::option::Option<usize> usize::checked_rem_euclid( const usize& rhs) const& noexcept { if (rhs.primitive_value == 0u) [[unlikely]] { return ::sus::option::Option<usize>(); } else { return ::sus::option::Option<usize>::with( usize(__private::unchecked_rem(primitive_value, rhs.primitive_value))); } } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<usize, bool> usize::overflowing_rem_euclid(const usize& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return ::sus::tuple_type::Tuple<usize, bool>::with( usize(__private::unchecked_rem(primitive_value, rhs.primitive_value)), false); } __attribute__((pure)) constexpr ::sus::option::Option<usize> usize::checked_shl( const u32& rhs) const& noexcept { const auto out = __private::shl_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return ::sus::option::Option<usize>::with(usize(out.value)); else return ::sus::option::Option<usize>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<usize, bool> usize::overflowing_shl( const u32& rhs) const& noexcept { const auto out = __private::shl_with_overflow(primitive_value, rhs.primitive_value); return ::sus::tuple_type::Tuple<usize, bool>::with(usize(out.value), out.overflow); } __attribute__((pure)) constexpr ::sus::option::Option<usize> usize::checked_shr( const u32& rhs) const& noexcept { const auto out = __private::shr_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return ::sus::option::Option<usize>::with(usize(out.value)); else return ::sus::option::Option<usize>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<usize, bool> usize::overflowing_shr( const u32& rhs) const& noexcept { const auto out = __private::shr_with_overflow(primitive_value, rhs.primitive_value); return ::sus::tuple_type::Tuple<usize, bool>::with(usize(out.value), out.overflow); } __attribute__((pure)) constexpr ::sus::option::Option<usize> usize::checked_sub( const usize& rhs) const& { const auto out = __private::sub_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return ::sus::option::Option<usize>::with(usize(out.value)); else return ::sus::option::Option<usize>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<usize, bool> usize::overflowing_sub( const usize& rhs) const& noexcept { const auto out = __private::sub_with_overflow(primitive_value, rhs.primitive_value); return ::sus::tuple_type::Tuple<usize, bool>::with(usize(out.value), out.overflow); } __attribute__((pure)) constexpr ::sus::option::Option<usize> usize::checked_pow( const u32& rhs) const& noexcept { const auto out = __private::pow_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return ::sus::option::Option<usize>::with(usize(out.value)); else return ::sus::option::Option<usize>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<usize, bool> usize::overflowing_pow( const u32& exp) const& noexcept { const auto out = __private::pow_with_overflow(primitive_value, exp.primitive_value); return ::sus::tuple_type::Tuple<usize, bool>::with(usize(out.value), out.overflow); } __attribute__((pure)) constexpr ::sus::option::Option<u32> usize::checked_log2() const& noexcept { if (primitive_value == 0u) [[unlikely]] { return ::sus::option::Option<u32>(); } else { uint32_t zeros = __private::leading_zeros_nonzero(::sus::marker::unsafe_fn, primitive_value); return ::sus::option::Option<u32>::with(BITS - u32(1u) - u32(zeros)); } } __attribute__((pure)) constexpr u32 usize::log2() const& noexcept { return checked_log2().unwrap(); } __attribute__((pure)) constexpr ::sus::option::Option<u32> usize::checked_log10() const& noexcept { if (primitive_value == 0u) [[unlikely]] { return ::sus::option::Option<u32>(); } else { return ::sus::option::Option<u32>::with( __private::int_log10::usize(primitive_value)); } } __attribute__((pure)) constexpr u32 usize::log10() const& noexcept { return checked_log10().unwrap(); } __attribute__((pure)) constexpr ::sus::option::Option<u32> usize::checked_log( const usize& base) const& noexcept { if (primitive_value == 0u || base.primitive_value <= 1u) [[unlikely]] { return ::sus::option::Option<u32>(); } else { auto n = uint32_t{0u}; auto r = primitive_value; const auto b = base.primitive_value; while (r >= b) { r /= b; n += 1u; } return ::sus::option::Option<u32>::with(n); } } __attribute__((pure)) constexpr u32 usize::log(const usize& base) const& noexcept { return checked_log(base).unwrap(); } __attribute__((pure)) constexpr ::sus::option::Option<usize> usize::checked_next_power_of_two() const& noexcept { const auto one_less = __private::one_less_than_next_power_of_two(primitive_value); return usize(one_less).checked_add(usize(::sus::num::__private::addr_type<>::unsigned_type{1u})); } __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of< ::sus::num::__private::addr_type<>::unsigned_type>()> usize::to_be_bytes() const& noexcept { return to_be().to_ne_bytes(); } __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of< ::sus::num::__private::addr_type<>::unsigned_type>()> usize::to_le_bytes() const& noexcept { return to_le().to_ne_bytes(); } __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of< ::sus::num::__private::addr_type<>::unsigned_type>()> usize::to_ne_bytes() const& noexcept { auto bytes = ::sus::containers::Array<u8, ::sus::mem::size_of< ::sus::num::__private::addr_type<>::unsigned_type>()>(); if (std::is_constant_evaluated()) { auto uval = primitive_value; for (auto i = size_t{0}; i < ::sus::mem::size_of< ::sus::num::__private::addr_type<>::unsigned_type>(); ++i) { const auto last_byte = static_cast<uint8_t>(uval & 0xff); if (sus::assertions::is_little_endian()) bytes[i] = last_byte; else bytes[::sus::mem::size_of< ::sus::num::__private::addr_type<>::unsigned_type>() - 1 - i] = last_byte; if constexpr (::sus::mem::size_of< ::sus::num::__private::addr_type<>::unsigned_type>() > 1) uval >>= 8u; } return bytes; } else { ::sus::ptr::copy_nonoverlapping( ::sus::marker::unsafe_fn, reinterpret_cast<const char*>(&primitive_value), reinterpret_cast<char*>(bytes.as_mut_ptr()), ::sus::mem::size_of< ::sus::num::__private::addr_type<>::unsigned_type>()); return bytes; } } __attribute__((pure)) constexpr usize usize::from_be_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of< ::sus::num::__private::addr_type<>::unsigned_type>()>& bytes) noexcept { return from_be(from_ne_bytes(bytes)); } __attribute__((pure)) constexpr usize usize::from_le_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of< ::sus::num::__private::addr_type<>::unsigned_type>()>& bytes) noexcept { return from_le(from_ne_bytes(bytes)); } __attribute__((pure)) constexpr usize usize::from_ne_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of< ::sus::num::__private::addr_type<>::unsigned_type>()>& bytes) noexcept { ::sus::num::__private::addr_type<>::unsigned_type val; if (std::is_constant_evaluated()) { val = 0u; for (auto i = size_t{0}; i < ::sus::mem::size_of< ::sus::num::__private::addr_type<>::unsigned_type>(); ++i) { val |= bytes[i].primitive_value << (::sus::mem::size_of< ::sus::num::__private::addr_type<>::unsigned_type>() - 1 - i); } } else { ::sus::ptr::copy_nonoverlapping( ::sus::marker::unsafe_fn, reinterpret_cast<const char*>(bytes.as_ptr()), reinterpret_cast<char*>(&val), ::sus::mem::size_of< ::sus::num::__private::addr_type<>::unsigned_type>()); } return usize(val); } } template <> struct std::hash<::sus::num::usize> { __attribute__((pure)) auto operator()(::sus::num::usize u) const noexcept { return std::hash< ::sus::num::__private::addr_type<>::unsigned_type>()(u.primitive_value); } }; template <> struct std::equal_to<::sus::num::usize> { __attribute__((pure)) constexpr auto operator()(::sus::num::usize l, ::sus::num::usize r) const noexcept { return l == r; } }; namespace sus::num { template <class U> __attribute__((pure)) constexpr ::sus::result::Result<uptr, ::sus::num::TryFromIntError> uptr::try_from(U* u) noexcept { using R = ::sus::result::Result<uptr, ::sus::num::TryFromIntError>; return R::with(uptr(reinterpret_cast< ::sus::num::__private::ptr_type<>::unsigned_type>(u))); } template <Unsigned U> requires(::sus::mem::size_of<U>() == ::sus::mem::size_of< ::sus::num::__private::ptr_type<>::unsigned_type>()) __attribute__((pure)) constexpr ::sus::result::Result<uptr, ::sus::num::TryFromIntError> uptr::try_from(U u) noexcept { using R = ::sus::result::Result<uptr, ::sus::num::TryFromIntError>; if constexpr (MAX_PRIMITIVE < U::MAX_PRIMITIVE) { if (u.primitive_value > MAX_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(uptr(static_cast< ::sus::num::__private::ptr_type<>::unsigned_type>(u.primitive_value))); } template <UnsignedPrimitiveInteger U> requires(::sus::mem::size_of<U>() == ::sus::mem::size_of< ::sus::num::__private::ptr_type<>::unsigned_type>()) __attribute__((pure)) constexpr ::sus::result::Result<uptr, ::sus::num::TryFromIntError> uptr::try_from(U u) noexcept { using R = ::sus::result::Result<uptr, ::sus::num::TryFromIntError>; if constexpr (MAX_PRIMITIVE < __private::max_value<U>()) { if (u > MAX_PRIMITIVE) { return R::with_err(::sus::num::TryFromIntError::with_out_of_bounds()); } } return R::with(uptr(static_cast< ::sus::num::__private::ptr_type<>::unsigned_type>(u))); } __attribute__((pure)) constexpr ::sus::option::Option<uptr> uptr::checked_add( const uptr& rhs) const& noexcept { const auto out = __private::add_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return ::sus::option::Option<uptr>::with(uptr(out.value)); else return ::sus::option::Option<uptr>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<uptr, bool> uptr::overflowing_add( const uptr& rhs) const& noexcept { const auto out = __private::add_with_overflow(primitive_value, rhs.primitive_value); return ::sus::tuple_type::Tuple<uptr, bool>::with(uptr(out.value), out.overflow); } __attribute__((pure)) constexpr ::sus::option::Option<uptr> uptr::checked_div( const uptr& rhs) const& noexcept { if (rhs.primitive_value != 0u) [[likely]] return ::sus::option::Option<uptr>::with( uptr(__private::unchecked_div(primitive_value, rhs.primitive_value))); else return ::sus::option::Option<uptr>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<uptr, bool> uptr::overflowing_div( const uptr& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return ::sus::tuple_type::Tuple<uptr, bool>::with( uptr(__private::unchecked_div(primitive_value, rhs.primitive_value)), false); } __attribute__((pure)) constexpr ::sus::option::Option<uptr> uptr::checked_mul( const uptr& rhs) const& noexcept { const auto out = __private::mul_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return ::sus::option::Option<uptr>::with(uptr(out.value)); else return ::sus::option::Option<uptr>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<uptr, bool> uptr::overflowing_mul( const uptr& rhs) const& noexcept { const auto out = __private::mul_with_overflow(primitive_value, rhs.primitive_value); return ::sus::tuple_type::Tuple<uptr, bool>::with(uptr(out.value), out.overflow); } __attribute__((pure)) constexpr ::sus::option::Option<uptr> uptr::checked_neg() const& noexcept { if (primitive_value == 0u) return ::sus::option::Option<uptr>::with(uptr(::sus::num::__private::ptr_type<>::unsigned_type{0u})); else return ::sus::option::Option<uptr>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<uptr, bool> uptr::overflowing_neg() const& noexcept { return ::sus::tuple_type::Tuple<uptr, bool>::with( (~(*this)).wrapping_add(uptr(::sus::num::__private::ptr_type<>::unsigned_type{1u})), primitive_value != 0u); } __attribute__((pure)) constexpr ::sus::option::Option<uptr> uptr::checked_rem( const uptr& rhs) const& noexcept { if (rhs.primitive_value != 0u) [[likely]] return ::sus::option::Option<uptr>::with( uptr(__private::unchecked_rem(primitive_value, rhs.primitive_value))); else return ::sus::option::Option<uptr>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<uptr, bool> uptr::overflowing_rem( const uptr& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return ::sus::tuple_type::Tuple<uptr, bool>::with( uptr(__private::unchecked_rem(primitive_value, rhs.primitive_value)), false); } __attribute__((pure)) constexpr ::sus::option::Option<uptr> uptr::checked_div_euclid( const uptr& rhs) const& noexcept { if (rhs.primitive_value == 0u) [[unlikely]] { return ::sus::option::Option<uptr>(); } else { return ::sus::option::Option<uptr>::with( uptr(__private::unchecked_div(primitive_value, rhs.primitive_value))); } } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<uptr, bool> uptr::overflowing_div_euclid(const uptr& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return ::sus::tuple_type::Tuple<uptr, bool>::with( uptr(__private::unchecked_div(primitive_value, rhs.primitive_value)), false); } __attribute__((pure)) constexpr ::sus::option::Option<uptr> uptr::checked_rem_euclid( const uptr& rhs) const& noexcept { if (rhs.primitive_value == 0u) [[unlikely]] { return ::sus::option::Option<uptr>(); } else { return ::sus::option::Option<uptr>::with( uptr(__private::unchecked_rem(primitive_value, rhs.primitive_value))); } } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<uptr, bool> uptr::overflowing_rem_euclid(const uptr& rhs) const& noexcept { ::sus::check(rhs.primitive_value != 0u); return ::sus::tuple_type::Tuple<uptr, bool>::with( uptr(__private::unchecked_rem(primitive_value, rhs.primitive_value)), false); } __attribute__((pure)) constexpr ::sus::option::Option<uptr> uptr::checked_shl( const u32& rhs) const& noexcept { const auto out = __private::shl_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return ::sus::option::Option<uptr>::with(uptr(out.value)); else return ::sus::option::Option<uptr>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<uptr, bool> uptr::overflowing_shl( const u32& rhs) const& noexcept { const auto out = __private::shl_with_overflow(primitive_value, rhs.primitive_value); return ::sus::tuple_type::Tuple<uptr, bool>::with(uptr(out.value), out.overflow); } __attribute__((pure)) constexpr ::sus::option::Option<uptr> uptr::checked_shr( const u32& rhs) const& noexcept { const auto out = __private::shr_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return ::sus::option::Option<uptr>::with(uptr(out.value)); else return ::sus::option::Option<uptr>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<uptr, bool> uptr::overflowing_shr( const u32& rhs) const& noexcept { const auto out = __private::shr_with_overflow(primitive_value, rhs.primitive_value); return ::sus::tuple_type::Tuple<uptr, bool>::with(uptr(out.value), out.overflow); } __attribute__((pure)) constexpr ::sus::option::Option<uptr> uptr::checked_sub( const uptr& rhs) const& { const auto out = __private::sub_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return ::sus::option::Option<uptr>::with(uptr(out.value)); else return ::sus::option::Option<uptr>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<uptr, bool> uptr::overflowing_sub( const uptr& rhs) const& noexcept { const auto out = __private::sub_with_overflow(primitive_value, rhs.primitive_value); return ::sus::tuple_type::Tuple<uptr, bool>::with(uptr(out.value), out.overflow); } __attribute__((pure)) constexpr ::sus::option::Option<uptr> uptr::checked_pow( const u32& rhs) const& noexcept { const auto out = __private::pow_with_overflow(primitive_value, rhs.primitive_value); if (!out.overflow) [[likely]] return ::sus::option::Option<uptr>::with(uptr(out.value)); else return ::sus::option::Option<uptr>(); } __attribute__((pure)) constexpr ::sus::tuple_type::Tuple<uptr, bool> uptr::overflowing_pow( const u32& exp) const& noexcept { const auto out = __private::pow_with_overflow(primitive_value, exp.primitive_value); return ::sus::tuple_type::Tuple<uptr, bool>::with(uptr(out.value), out.overflow); } __attribute__((pure)) constexpr ::sus::option::Option<u32> uptr::checked_log2() const& noexcept { if (primitive_value == 0u) [[unlikely]] { return ::sus::option::Option<u32>(); } else { uint32_t zeros = __private::leading_zeros_nonzero(::sus::marker::unsafe_fn, primitive_value); return ::sus::option::Option<u32>::with(BITS - u32(1u) - u32(zeros)); } } __attribute__((pure)) constexpr u32 uptr::log2() const& noexcept { return checked_log2().unwrap(); } __attribute__((pure)) constexpr ::sus::option::Option<u32> uptr::checked_log10() const& noexcept { if (primitive_value == 0u) [[unlikely]] { return ::sus::option::Option<u32>(); } else { return ::sus::option::Option<u32>::with( __private::int_log10::uptr(primitive_value)); } } __attribute__((pure)) constexpr u32 uptr::log10() const& noexcept { return checked_log10().unwrap(); } __attribute__((pure)) constexpr ::sus::option::Option<u32> uptr::checked_log( const uptr& base) const& noexcept { if (primitive_value == 0u || base.primitive_value <= 1u) [[unlikely]] { return ::sus::option::Option<u32>(); } else { auto n = uint32_t{0u}; auto r = primitive_value; const auto b = base.primitive_value; while (r >= b) { r /= b; n += 1u; } return ::sus::option::Option<u32>::with(n); } } __attribute__((pure)) constexpr u32 uptr::log(const uptr& base) const& noexcept { return checked_log(base).unwrap(); } __attribute__((pure)) constexpr ::sus::option::Option<uptr> uptr::checked_next_power_of_two() const& noexcept { const auto one_less = __private::one_less_than_next_power_of_two(primitive_value); return uptr(one_less).checked_add(uptr(::sus::num::__private::ptr_type<>::unsigned_type{1u})); } __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of< ::sus::num::__private::ptr_type<>::unsigned_type>()> uptr::to_be_bytes() const& noexcept { return to_be().to_ne_bytes(); } __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of< ::sus::num::__private::ptr_type<>::unsigned_type>()> uptr::to_le_bytes() const& noexcept { return to_le().to_ne_bytes(); } __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of< ::sus::num::__private::ptr_type<>::unsigned_type>()> uptr::to_ne_bytes() const& noexcept { auto bytes = ::sus::containers::Array<u8, ::sus::mem::size_of< ::sus::num::__private::ptr_type<>::unsigned_type>()>(); if (std::is_constant_evaluated()) { auto uval = primitive_value; for (auto i = size_t{0}; i < ::sus::mem::size_of< ::sus::num::__private::ptr_type<>::unsigned_type>(); ++i) { const auto last_byte = static_cast<uint8_t>(uval & 0xff); if (sus::assertions::is_little_endian()) bytes[i] = last_byte; else bytes[::sus::mem::size_of< ::sus::num::__private::ptr_type<>::unsigned_type>() - 1 - i] = last_byte; if constexpr (::sus::mem::size_of< ::sus::num::__private::ptr_type<>::unsigned_type>() > 1) uval >>= 8u; } return bytes; } else { ::sus::ptr::copy_nonoverlapping( ::sus::marker::unsafe_fn, reinterpret_cast<const char*>(&primitive_value), reinterpret_cast<char*>(bytes.as_mut_ptr()), ::sus::mem::size_of< ::sus::num::__private::ptr_type<>::unsigned_type>()); return bytes; } } __attribute__((pure)) constexpr uptr uptr::from_be_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of< ::sus::num::__private::ptr_type<>::unsigned_type>()>& bytes) noexcept { return from_be(from_ne_bytes(bytes)); } __attribute__((pure)) constexpr uptr uptr::from_le_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of< ::sus::num::__private::ptr_type<>::unsigned_type>()>& bytes) noexcept { return from_le(from_ne_bytes(bytes)); } __attribute__((pure)) constexpr uptr uptr::from_ne_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of< ::sus::num::__private::ptr_type<>::unsigned_type>()>& bytes) noexcept { ::sus::num::__private::ptr_type<>::unsigned_type val; if (std::is_constant_evaluated()) { val = 0u; for (auto i = size_t{0}; i < ::sus::mem::size_of< ::sus::num::__private::ptr_type<>::unsigned_type>(); ++i) { val |= bytes[i].primitive_value << (::sus::mem::size_of< ::sus::num::__private::ptr_type<>::unsigned_type>() - 1 - i); } } else { ::sus::ptr::copy_nonoverlapping( ::sus::marker::unsafe_fn, reinterpret_cast<const char*>(bytes.as_ptr()), reinterpret_cast<char*>(&val), ::sus::mem::size_of< ::sus::num::__private::ptr_type<>::unsigned_type>()); } return uptr(val); } } template <> struct std::hash<::sus::num::uptr> { __attribute__((pure)) auto operator()(::sus::num::uptr u) const noexcept { return std::hash< ::sus::num::__private::ptr_type<>::unsigned_type>()(u.primitive_value); } }; template <> struct std::equal_to<::sus::num::uptr> { __attribute__((pure)) constexpr auto operator()(::sus::num::uptr l, ::sus::num::uptr r) const noexcept { return l == r; } }; namespace sus::iter { template <class RefIterator> class [[nodiscard]] ByRef final : public IteratorBase<ByRef<RefIterator>, typename RefIterator::Item> { public: using Item = RefIterator::Item; constexpr Option<Item> next() noexcept { return next_iter_->next(); } constexpr SizeHint size_hint() const noexcept { return next_iter_->size_hint(); } constexpr Option<Item> next_back() noexcept requires(DoubleEndedIterator<RefIterator, Item>) { return next_iter_->next_back(); } constexpr usize exact_size_hint() const noexcept requires(ExactSizeIterator<RefIterator, Item>) { return next_iter_->exact_size_hint(); } constexpr ~ByRef() noexcept { } private: template <class U, class V> friend class IteratorBase; static constexpr ByRef with( RefIterator& next_iter) noexcept { return ByRef(next_iter); } constexpr ByRef(RefIterator& next_iter) noexcept : next_iter_(::sus::mem::addressof(next_iter)) { } RefIterator* next_iter_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(next_iter_)>; static_assert(SusUnsafeTrivialRelocate, "Type is not trivially relocatable"); }; } namespace sus::iter { namespace __private { template <class T, class U> constexpr inline Option<U> and_then_or_clear( Option<T>& opt, ::sus::fn::FnOnce<Option<U>(T&)> auto&& f) { if (opt.is_none()) { return Option<U>(); } else { return ::sus::fn::call_once(::sus::move(f), *opt).or_else([&opt]() { opt = Option<T>(); return Option<U>(); }); } } } template <class InnerSizedIter, class OtherSizedIter> class [[nodiscard]] Chain final : public IteratorBase<Chain<InnerSizedIter, OtherSizedIter>, typename InnerSizedIter::Item> { public: using Item = typename InnerSizedIter::Item; constexpr Option<Item> next() noexcept { return __private::and_then_or_clear<InnerSizedIter, Item>( first_iter_, [](InnerSizedIter& iter) { return iter.next(); }) .or_else([this] { if (second_iter_.is_some()) return second_iter_->next(); else return Option<Item>(); }); } constexpr Option<Item> next_back() noexcept requires(DoubleEndedIterator<InnerSizedIter, Item> && DoubleEndedIterator<OtherSizedIter, Item>) { return __private::and_then_or_clear<OtherSizedIter, Item>( second_iter_, [](OtherSizedIter& iter) { return iter.next_back(); }) .or_else([this] { if (first_iter_.is_some()) return first_iter_->next(); else return Option<Item>(); }); } constexpr SizeHint size_hint() const noexcept { if (first_iter_.is_none()) { if (second_iter_.is_none()) { return SizeHint(0u, sus::Option<usize>::with(0u)); } else { return second_iter_->size_hint(); } } else { if (second_iter_.is_none()) { return first_iter_->size_hint(); } else { auto [fst_lower, fst_upper] = first_iter_->size_hint(); auto [snd_lower, snd_upper] = second_iter_->size_hint(); auto lower = fst_lower.saturating_add(snd_lower); if (fst_upper.is_some() && snd_upper.is_some()) return SizeHint(lower, (*fst_upper).checked_add(*snd_upper)); else return SizeHint(lower, ::sus::Option<::sus::num::usize>()); } } } private: template <class U, class V> friend class IteratorBase; static constexpr Chain with(InnerSizedIter&& first_iter, OtherSizedIter&& second_iter) noexcept { return Chain(::sus::move(first_iter), ::sus::move(second_iter)); } constexpr Chain(InnerSizedIter&& first_iter, OtherSizedIter&& second_iter) : first_iter_( ::sus::Option<InnerSizedIter>::with(::sus::move(first_iter))), second_iter_( ::sus::Option<OtherSizedIter>::with(::sus::move(second_iter))) {} ::sus::Option<InnerSizedIter> first_iter_; ::sus::Option<OtherSizedIter> second_iter_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(first_iter_), decltype(second_iter_)>; }; } namespace sus::iter { template <class InnerSizedIter> class [[nodiscard]] Cloned final : public IteratorBase<Cloned<InnerSizedIter>, std::remove_cvref_t<typename InnerSizedIter::Item>> { public: using Item = std::remove_cvref_t<typename InnerSizedIter::Item>; Option<Item> next() noexcept { return next_iter_.next().map( [](const Item& item) { return ::sus::clone(item); }); } SizeHint size_hint() const noexcept { return next_iter_.size_hint(); } Option<Item> next_back() noexcept requires(DoubleEndedIterator<InnerSizedIter, Item>) { return next_iter_.next_back().map( [](const Item& item) { return ::sus::clone(item); }); } usize exact_size_hint() const noexcept requires(ExactSizeIterator<InnerSizedIter, Item>) { return next_iter_.exact_size_hint(); } private: template <class U, class V> friend class IteratorBase; static Cloned with(InnerSizedIter&& next_iter) noexcept { return Cloned(::sus::move(next_iter)); } Cloned(InnerSizedIter&& next_iter) : next_iter_(::sus::move(next_iter)) {} InnerSizedIter next_iter_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(next_iter_)>; }; } namespace sus::iter { template <class InnerSizedIter> class [[nodiscard]] Copied final : public IteratorBase<Copied<InnerSizedIter>, std::remove_cvref_t<typename InnerSizedIter::Item>> { public: using Item = std::remove_cvref_t<typename InnerSizedIter::Item>; Option<Item> next() noexcept { return next_iter_.next().map([](const Item& item) -> Item { return item; }); } SizeHint size_hint() const noexcept { return next_iter_.size_hint(); } Option<Item> next_back() noexcept requires(DoubleEndedIterator<InnerSizedIter, Item>) { return next_iter_.next_back().map( [](const Item& item) -> Item { return item; }); } usize exact_size_hint() const noexcept requires(ExactSizeIterator<InnerSizedIter, Item>) { return next_iter_.exact_size_hint(); } private: template <class U, class V> friend class IteratorBase; static Copied with(InnerSizedIter&& next_iter) noexcept { return Copied(::sus::move(next_iter)); } Copied(InnerSizedIter&& next_iter) : next_iter_(::sus::move(next_iter)) {} InnerSizedIter next_iter_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(next_iter_)>; }; } namespace sus::iter { template <class InnerSizedIter> class [[nodiscard]] Cycle final : public IteratorBase<Cycle<InnerSizedIter>, typename InnerSizedIter::Item> { static_assert(::sus::mem::Clone<InnerSizedIter>); public: using Item = typename InnerSizedIter::Item; Cycle(Cycle&&) = default; Cycle& operator=(Cycle&&) = default; Cycle clone() const noexcept { return Cycle(::sus::clone(original_), ::sus::clone(active_)); } constexpr Option<Item> next() noexcept { auto o = active_.next(); if (o.is_none()) { active_ = ::sus::clone(original_); o = active_.next(); } return o; } constexpr SizeHint size_hint() const noexcept { SizeHint sz = original_.size_hint(); if (sz.lower != 0u) { return SizeHint(usize::MAX, ::sus::Option<usize>()); } return SizeHint(0u, ::sus::move(sz).upper.map_or_else( [] { return ::sus::Option<usize>(); }, [](usize u) { if (u == 0u) { return ::sus::Option<usize>::with(0u); } else return ::sus::Option<usize>(); })); } private: template <class U, class V> friend class IteratorBase; static constexpr Cycle with(InnerSizedIter&& iter) noexcept { return Cycle(::sus::clone(iter), ::sus::move(iter)); } constexpr Cycle(InnerSizedIter&& original, InnerSizedIter&& active) : original_(::sus::move(original)), active_(::sus::move(active)) {} InnerSizedIter original_; InnerSizedIter active_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(original_), decltype(active_)>; }; } namespace sus::iter { template <class InnerSizedIter> class [[nodiscard]] Enumerate final : public IteratorBase<Enumerate<InnerSizedIter>, ::sus::Tuple<usize, typename InnerSizedIter::Item>> { using FromItem = typename InnerSizedIter::Item; public: using Item = ::sus::Tuple<usize, FromItem>; constexpr Option<Item> next() noexcept { Option<typename InnerSizedIter::Item> item = next_iter_.next(); if (item.is_none()) { return sus::none(); } else { usize count = count_; count_ += 1u; return sus::some(sus::tuple( count, sus::move(item).unwrap_unchecked(::sus::marker::unsafe_fn))); } } constexpr SizeHint size_hint() const noexcept { return next_iter_.size_hint(); } constexpr Option<Item> next_back() noexcept requires(DoubleEndedIterator<InnerSizedIter, FromItem> && ExactSizeIterator<InnerSizedIter, FromItem>) { Option<FromItem> item = next_iter_.next_back(); if (item.is_none()) { return sus::none(); } else { usize len = next_iter_.exact_size_hint(); return sus::some(sus::tuple( count_ + len, sus::move(item).unwrap_unchecked(::sus::marker::unsafe_fn))); } } constexpr usize exact_size_hint() const noexcept requires(ExactSizeIterator<InnerSizedIter, FromItem>) { return next_iter_.exact_size_hint(); } private: template <class U, class V> friend class IteratorBase; static constexpr Enumerate with(InnerSizedIter&& next_iter) noexcept { return Enumerate(::sus::move(next_iter)); } constexpr Enumerate(InnerSizedIter&& next_iter) : next_iter_(::sus::move(next_iter)) {} usize count_ = 0u; InnerSizedIter next_iter_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(next_iter_)>; }; } namespace sus::iter { using ::sus::mem::relocate_by_memcpy; template <class InnerSizedIter, class Pred> class [[nodiscard]] Filter final : public IteratorBase<Filter<InnerSizedIter, Pred>, typename InnerSizedIter::Item> { public: using Item = InnerSizedIter::Item; static_assert( ::sus::fn::FnMut<Pred, bool(const std::remove_reference_t<Item>&)>); constexpr Option<Item> next() noexcept { while (true) { Option<Item> item = next_iter_.next(); if (item.is_none() || ::sus::fn::call_mut(pred_, item.as_value())) return item; } } constexpr SizeHint size_hint() const noexcept { return SizeHint(0u, next_iter_.size_hint().upper); } constexpr Option<Item> next_back() noexcept requires(DoubleEndedIterator<InnerSizedIter, Item>) { while (true) { Option<Item> item = next_iter_.next_back(); if (item.is_none() || ::sus::fn::call_mut(pred_, item.as_value())) return item; } } private: template <class U, class V> friend class IteratorBase; static constexpr Filter with(Pred&& pred, InnerSizedIter&& next_iter) noexcept { return Filter(::sus::move(pred), ::sus::move(next_iter)); } constexpr Filter(Pred&& pred, InnerSizedIter&& next_iter) noexcept : pred_(::sus::move(pred)), next_iter_(::sus::move(next_iter)) {} Pred pred_; InnerSizedIter next_iter_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(pred_), decltype(next_iter_)>; }; } namespace sus::iter { using ::sus::mem::relocate_by_memcpy; template <class ToItem, class InnerSizedIter, class FilterMapFn> class [[nodiscard]] FilterMap final : public IteratorBase<FilterMap<ToItem, InnerSizedIter, FilterMapFn>, ToItem> { using FromItem = InnerSizedIter::Item; static_assert( ::sus::fn::FnMut<FilterMapFn, ::sus::Option<ToItem>(FromItem&&)>); public: using Item = ToItem; constexpr FilterMap clone() const noexcept requires(::sus::mem::Clone<InnerSizedIter>) { return FilterMap(sus::clone(fn_), sus::clone(next_iter_)); } constexpr Option<Item> next() noexcept { while (true) { Option<FromItem> in = next_iter_.next(); Option<ToItem> out; if (in.is_none()) return out; out = ::sus::fn::call_mut(fn_, sus::move(in).unwrap()); if (out.is_some()) return out; } } constexpr SizeHint size_hint() const noexcept { return SizeHint(0u, next_iter_.size_hint().upper); } constexpr Option<Item> next_back() noexcept requires(DoubleEndedIterator<InnerSizedIter, FromItem>) { while (true) { Option<FromItem> in = next_iter_.next_back(); Option<ToItem> out; if (in.is_none()) return out; out = ::sus::fn::call_mut(fn_, sus::move(in).unwrap()); if (out.is_some()) return out; } } private: template <class U, class V> friend class IteratorBase; static constexpr FilterMap with(FilterMapFn&& fn, InnerSizedIter&& next_iter) noexcept { return FilterMap(::sus::move(fn), ::sus::move(next_iter)); } constexpr FilterMap(FilterMapFn&& fn, InnerSizedIter&& next_iter) noexcept : fn_(::sus::move(fn)), next_iter_(::sus::move(next_iter)) {} FilterMapFn fn_; InnerSizedIter next_iter_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(fn_), decltype(next_iter_)>; }; } namespace sus::iter { template <class IntoIterable, class InnerSizedIter, class MapFn> class [[nodiscard]] FlatMap final : public IteratorBase<FlatMap<IntoIterable, InnerSizedIter, MapFn>, typename IntoIteratorOutputType<IntoIterable>::Item> { using EachIter = IntoIteratorOutputType<IntoIterable>; static_assert( ::sus::fn::FnMut<MapFn, IntoIterable(typename InnerSizedIter::Item&&)>); public: using Item = typename EachIter::Item; constexpr Option<Item> next() noexcept { Option<Item> out; while (true) { if (front_iter_.is_some()) { out = front_iter_.as_value_mut().next(); if (out.is_some()) return out; front_iter_ = Option<EachIter>(); } front_iter_ = iters_.next().map([this](auto&& i) { return ::sus::fn::call_mut(map_fn_, ::sus::move(i)).into_iter(); }); if (front_iter_.is_none()) break; } if (back_iter_.is_some()) { out = back_iter_.as_value_mut().next(); if (out.is_some()) return out; back_iter_ = Option<EachIter>(); } return out; } constexpr SizeHint size_hint() const noexcept { auto [flo, fhi] = front_iter_.as_ref().map_or( SizeHint(0u, ::sus::some(0u)), [](const EachIter& i) { return i.size_hint(); }); auto [blo, bhi] = back_iter_.as_ref().map_or( SizeHint(0u, ::sus::some(0u)), [](const EachIter& i) { return i.size_hint(); }); usize lo = flo.saturating_add(blo); return SizeHint(lo, ::sus::Option<usize>()); } constexpr Option<Item> next_back() noexcept requires(DoubleEndedIterator<InnerSizedIter, typename InnerSizedIter::Item> && DoubleEndedIterator<EachIter, Item>) { Option<Item> out; while (true) { if (back_iter_.is_some()) { out = back_iter_.as_value_mut().next_back(); if (out.is_some()) return out; back_iter_ = Option<EachIter>(); } back_iter_ = iters_.next_back().map([this](auto&& i) { return ::sus::fn::call_mut(map_fn_, ::sus::move(i)).into_iter(); }); if (back_iter_.is_none()) break; } if (front_iter_.is_some()) { out = front_iter_.as_value_mut().next(); if (out.is_some()) return out; front_iter_ = Option<EachIter>(); } return out; } private: template <class U, class V> friend class IteratorBase; static constexpr FlatMap with(MapFn&& fn, InnerSizedIter&& iters) noexcept { return FlatMap(::sus::move(fn), ::sus::move(iters)); } constexpr FlatMap(MapFn&& fn, InnerSizedIter&& iters) : map_fn_(::sus::move(fn)), iters_(::sus::move(iters)) {} MapFn map_fn_; InnerSizedIter iters_; ::sus::Option<EachIter> front_iter_; ::sus::Option<EachIter> back_iter_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(map_fn_), decltype(iters_), decltype(front_iter_), decltype(front_iter_)>; }; } namespace sus::iter { template <class EachIter, class InnerSizedIter> class [[nodiscard]] Flatten final : public IteratorBase<Flatten<EachIter, InnerSizedIter>, typename EachIter::Item> { public: using Item = typename EachIter::Item; constexpr Option<Item> next() noexcept { Option<Item> out; while (true) { if (front_iter_.is_some()) { out = front_iter_.as_value_mut().next(); if (out.is_some()) return out; front_iter_ = Option<EachIter>(); } front_iter_ = iters_.next().map( [](auto&& i) { return ::sus::move(i).into_iter(); }); if (front_iter_.is_none()) break; } if (back_iter_.is_some()) { out = back_iter_.as_value_mut().next(); if (out.is_some()) return out; back_iter_ = Option<EachIter>(); } return out; } constexpr SizeHint size_hint() const noexcept { auto [flo, fhi] = front_iter_.as_ref().map_or( SizeHint(0u, ::sus::some(0u)), [](const EachIter& i) { return i.size_hint(); }); auto [blo, bhi] = back_iter_.as_ref().map_or( SizeHint(0u, ::sus::some(0u)), [](const EachIter& i) { return i.size_hint(); }); usize lo = flo.saturating_add(blo); return SizeHint(lo, ::sus::Option<usize>()); } constexpr Option<Item> next_back() noexcept requires(DoubleEndedIterator<InnerSizedIter, typename InnerSizedIter::Item> && DoubleEndedIterator<EachIter, Item>) { Option<Item> out; while (true) { if (back_iter_.is_some()) { out = back_iter_.as_value_mut().next_back(); if (out.is_some()) return out; back_iter_ = Option<EachIter>(); } back_iter_ = iters_.next_back().map( [](auto&& i) { return ::sus::move(i).into_iter(); }); if (back_iter_.is_none()) break; } if (front_iter_.is_some()) { out = front_iter_.as_value_mut().next(); if (out.is_some()) return out; front_iter_ = Option<EachIter>(); } return out; } private: template <class U, class V> friend class IteratorBase; static constexpr Flatten with(InnerSizedIter&& iters) noexcept { return Flatten(::sus::move(iters)); } constexpr Flatten(InnerSizedIter&& iters) : iters_(::sus::move(iters)) {} InnerSizedIter iters_; ::sus::Option<EachIter> front_iter_; ::sus::Option<EachIter> back_iter_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(iters_), decltype(front_iter_), decltype(front_iter_)>; }; } namespace sus::iter { using ::sus::mem::relocate_by_memcpy; template <class InnerIter> class [[nodiscard]] Fuse final : public IteratorBase<Fuse<InnerIter>, typename InnerIter::Item> { public: using Item = InnerIter::Item; constexpr Option<Item> next() noexcept { Option<Item> o; if (iter_.is_some()) { o = iter_.as_value_mut().next(); if (o.is_none()) iter_ = Option<InnerIter>(); } return o; } constexpr SizeHint size_hint() const noexcept { if (iter_.is_some()) return iter_.as_value().size_hint(); else return SizeHint(0u, Option<usize>::with(0u)); } constexpr Option<Item> next_back() noexcept requires(DoubleEndedIterator<InnerIter, Item>) { Option<Item> o; if (iter_.is_some()) { o = iter_.as_value_mut().next_back(); if (o.is_none()) iter_ = Option<InnerIter>(); } return o; } private: template <class U, class V> friend class IteratorBase; static constexpr Fuse with(InnerIter&& iter) noexcept { return Fuse(::sus::move(iter)); } constexpr Fuse(InnerIter&& iter) noexcept : iter_(::sus::Option<InnerIter>::with(::sus::move(iter))) {} ::sus::Option<InnerIter> iter_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(iter_)>; }; } namespace sus::iter { template <class InnerSizedIter, class InspectFn> class [[nodiscard]] Inspect final : public IteratorBase<Inspect<InnerSizedIter, InspectFn>, typename InnerSizedIter::Item> { public: using Item = typename InnerSizedIter::Item; static_assert( ::sus::fn::FnMut<InspectFn, void(const std::remove_reference_t<Item>&)>); Inspect(Inspect&&) = default; Inspect& operator=(Inspect&&) = default; constexpr Inspect clone() noexcept requires(::sus::mem::Clone<InnerSizedIter>) { return Inspect(::sus::clone(inspect_), ::sus::clone(next_iter_)); } constexpr Option<Item> next() noexcept { Option<Item> item = next_iter_.next(); if (item.is_some()) ::sus::fn::call_mut(inspect_, item.as_value()); return item; } constexpr SizeHint size_hint() const noexcept { return next_iter_.size_hint(); } constexpr Option<Item> next_back() noexcept requires(DoubleEndedIterator<InnerSizedIter, Item>) { Option<Item> item = next_iter_.next_back(); if (item.is_some()) ::sus::fn::call_mut(inspect_, item.as_value()); return item; } constexpr usize exact_size_hint() const noexcept requires(ExactSizeIterator<InnerSizedIter, Item>) { return next_iter_.exact_size_hint(); } private: template <class U, class V> friend class IteratorBase; static constexpr Inspect with(InspectFn fn, InnerSizedIter&& next_iter) noexcept { return Inspect(::sus::move(fn), ::sus::move(next_iter)); } constexpr Inspect(InspectFn&& fn, InnerSizedIter&& next_iter) : inspect_(::sus::move(fn)), next_iter_(::sus::move(next_iter)) {} InspectFn inspect_; InnerSizedIter next_iter_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(inspect_), decltype(next_iter_)>; }; } namespace sus::iter { template <class ToItem, class InnerSizedIter> class [[nodiscard]] Map final : public IteratorBase<Map<ToItem, InnerSizedIter>, ToItem> { using FromItem = InnerSizedIter::Item; using MapFn = ::sus::fn::FnMutBox<ToItem(FromItem&&)>; public: using Item = ToItem; Option<Item> next() noexcept { Option<FromItem> item = next_iter_.next(); if (item.is_none()) { return sus::none(); } else { return sus::some(::sus::fn::call_mut( fn_, sus::move(item).unwrap_unchecked(::sus::marker::unsafe_fn))); } } SizeHint size_hint() const noexcept { return next_iter_.size_hint(); } Option<Item> next_back() noexcept requires(DoubleEndedIterator<InnerSizedIter, FromItem>) { Option<FromItem> item = next_iter_.next_back(); if (item.is_none()) { return sus::none(); } else { return sus::some(::sus::fn::call_mut( fn_, sus::move(item).unwrap_unchecked(::sus::marker::unsafe_fn))); } } usize exact_size_hint() const noexcept requires(ExactSizeIterator<InnerSizedIter, FromItem>) { return next_iter_.exact_size_hint(); } private: template <class U, class V> friend class IteratorBase; static Map with(MapFn fn, InnerSizedIter&& next_iter) noexcept { return Map(::sus::move(fn), ::sus::move(next_iter)); } Map(MapFn fn, InnerSizedIter&& next_iter) : fn_(::sus::move(fn)), next_iter_(::sus::move(next_iter)) {} MapFn fn_; InnerSizedIter next_iter_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(fn_), decltype(next_iter_)>; }; } namespace sus::iter { template <class ToItem, class InnerSizedIter> class [[nodiscard]] MapWhile final : public IteratorBase<MapWhile<ToItem, InnerSizedIter>, ToItem> { using FromItem = InnerSizedIter::Item; using MapFn = ::sus::fn::FnMutBox<::sus::Option<ToItem>(FromItem&&)>; public: using Item = ToItem; MapWhile clone() const noexcept requires(::sus::mem::Clone<InnerSizedIter>) { return MapWhile(::sus::clone(fn_), ::sus::clone(next_iter_)); } Option<Item> next() noexcept { Option<FromItem> item = next_iter_.next(); if (item.is_none()) { return sus::none(); } else { return ::sus::fn::call_mut( fn_, sus::move(item).unwrap_unchecked(::sus::marker::unsafe_fn)); } } SizeHint size_hint() const noexcept { return SizeHint(0u, next_iter_.size_hint().upper); } Option<Item> next_back() noexcept requires(DoubleEndedIterator<InnerSizedIter, FromItem>) { Option<FromItem> item = next_iter_.next_back(); if (item.is_none()) { return sus::none(); } else { return ::sus::fn::call_mut( fn_, sus::move(item).unwrap_unchecked(::sus::marker::unsafe_fn)); } } private: template <class U, class V> friend class IteratorBase; static MapWhile with(MapFn fn, InnerSizedIter&& next_iter) noexcept { return MapWhile(::sus::move(fn), ::sus::move(next_iter)); } MapWhile(MapFn fn, InnerSizedIter&& next_iter) : fn_(::sus::move(fn)), next_iter_(::sus::move(next_iter)) {} MapFn fn_; InnerSizedIter next_iter_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(fn_), decltype(next_iter_)>; }; } namespace sus::iter { using ::sus::mem::relocate_by_memcpy; template <class InnerSizedIter> class [[nodiscard]] Peekable final : public IteratorBase<Peekable<InnerSizedIter>, typename InnerSizedIter::Item> { public: using Item = InnerSizedIter::Item; Peekable(Peekable&&) = default; Peekable& operator=(Peekable&&) = default; Peekable clone() const noexcept requires(::sus::mem::Clone<InnerSizedIter> && ::sus::mem::CloneOrRef<Item>) { return Peekable(::sus::clone(peeked_), ::sus::clone(next_iter_)); } Option<const std::remove_reference_t<Item>&> peek() noexcept { return peeked_.get_or_insert_with([this] { return next_iter_.next(); }) .as_ref(); } Option<Item&> peek_mut() noexcept { return peeked_.get_or_insert_with([this] { return next_iter_.next(); }) .as_mut(); } Option<Item> next_if( ::sus::fn::FnOnceRef<bool(const std::remove_reference_t<Item>&)> pred) noexcept { Option<Item> o = next(); if (o.is_some() && ::sus::fn::call_once(::sus::move(pred), o.as_value())) { return o; } else { peeked_.insert(o.take()); return o; } } Option<Item> next_if_eq( const std::remove_reference_t<Item>& expected) noexcept requires(::sus::ops::Eq<Item>) { return next_if([&](const auto& i) { return i == expected; }); } Option<Item> next() noexcept { return peeked_.take().unwrap_or_else( [this]() { return next_iter_.next(); }); } SizeHint size_hint() const noexcept { usize peek_len; if (peeked_.is_some()) { if (peeked_.as_value().is_some()) { peek_len = 1u; } else { return SizeHint(0u, sus::some(0u)); } } auto [lo, hi] = next_iter_.size_hint(); return SizeHint( lo.saturating_add(peek_len), hi.and_then([&](usize i) { return i.checked_add(peek_len); })); } Option<Item> next_back() noexcept requires(DoubleEndedIterator<InnerSizedIter, Item>) { if (peeked_.is_some()) { if (peeked_.as_value().is_some()) { return next_iter_.next_back().or_else([this] { return peeked_.as_value_mut().take(); }); } else { return Option<Item>(); } } else { return next_iter_.next_back(); } } usize exact_size_hint() const noexcept requires(ExactSizeIterator<InnerSizedIter, Item>) { if (peeked_.is_some()) { if (peeked_.as_value().is_some()) { return 1u + next_iter_.exact_size_hint(); } else { return 0u; } } return next_iter_.exact_size_hint(); } private: template <class U, class V> friend class IteratorBase; static Peekable with(InnerSizedIter&& next_iter) noexcept { return Peekable(::sus::move(next_iter)); } Peekable(InnerSizedIter&& next_iter) : next_iter_(::sus::move(next_iter)) {} Peekable(::sus::Option<::sus::Option<Item>>&& peeked, InnerSizedIter&& next_iter) : peeked_(::sus::move(peeked)), next_iter_(::sus::move(next_iter)) {} ::sus::Option<::sus::Option<Item>> peeked_; InnerSizedIter next_iter_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(peeked_), decltype(next_iter_)>; }; } namespace sus::iter { using ::sus::mem::relocate_by_memcpy; template <class InnerSizedIter> class [[nodiscard]] Reverse final : public IteratorBase<Reverse<InnerSizedIter>, typename InnerSizedIter::Item> { static_assert( DoubleEndedIterator<InnerSizedIter, typename InnerSizedIter::Item>); public: using Item = InnerSizedIter::Item; Option<Item> next() noexcept { return next_iter_.next_back(); } SizeHint size_hint() const noexcept { return next_iter_.size_hint(); } Option<Item> next_back() noexcept { return next_iter_.next(); } usize exact_size_hint() const noexcept requires(ExactSizeIterator<InnerSizedIter, Item>) { return next_iter_.exact_size_hint(); } private: template <class U, class V> friend class IteratorBase; static Reverse with(InnerSizedIter&& next_iter) noexcept { return Reverse(::sus::move(next_iter)); } Reverse(InnerSizedIter&& next_iter) : next_iter_(::sus::move(next_iter)) {} InnerSizedIter next_iter_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(next_iter_)>; }; } namespace sus::iter { using ::sus::mem::relocate_by_memcpy; template <class OutType, class State, class InnerSizedIter> requires(!std::is_reference_v<State>) class [[nodiscard]] Scan final : public IteratorBase<Scan<OutType, State, InnerSizedIter>, OutType> { using Fn = ::sus::fn::FnMutBox<Option<OutType>( State&, typename InnerSizedIter::Item&&)>; public: using Item = OutType; Scan clone() const noexcept requires(::sus::mem::Clone<State> && ::sus::mem::Clone<InnerSizedIter>) { return Scan(::sus::clone(state_), ::sus::clone(fn_), ::sus::clone(next_iter_)); } Option<Item> next() noexcept { Option<Item> out; if (Option<typename InnerSizedIter::Item> o = next_iter_.next(); o.is_some()) { out = ::sus::fn::call_mut( fn_, state_, ::sus::move(o).unwrap_unchecked(::sus::marker::unsafe_fn)); } return out; } SizeHint size_hint() const noexcept { return SizeHint(0u, next_iter_.size_hint().upper); } private: template <class U, class V> friend class IteratorBase; static Scan with(State&& state, Fn&& fn, InnerSizedIter&& next_iter) noexcept { return Scan(::sus::move(state), ::sus::move(fn), ::sus::move(next_iter)); } Scan(State&& state, Fn&& fn, InnerSizedIter&& next_iter) noexcept : state_(::sus::move(state)), fn_(::sus::move(fn)), next_iter_(::sus::move(next_iter)) {} State state_; Fn fn_; InnerSizedIter next_iter_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(state_), decltype(fn_), decltype(next_iter_)>; }; } namespace sus::iter { using ::sus::mem::relocate_by_memcpy; template <class InnerSizedIter> class [[nodiscard]] Skip final : public IteratorBase<Skip<InnerSizedIter>, typename InnerSizedIter::Item> { public: using Item = InnerSizedIter::Item; Skip clone() const noexcept requires(::sus::mem::Clone<InnerSizedIter>) { return Skip(skip_, ::sus::clone(next_iter_)); } Option<Item> next() noexcept { while (skip_ > 0u) { next_iter_.next(); skip_ -= 1u; } return next_iter_.next(); } SizeHint size_hint() const noexcept { auto [lower, upper] = next_iter_.size_hint(); lower = lower.saturating_sub(skip_); upper = upper.map([this](usize upper) { return upper.saturating_sub(skip_); }); return {lower, upper}; } Option<Item> next_back() noexcept requires(DoubleEndedIterator<InnerSizedIter, Item> && ExactSizeIterator<InnerSizedIter, Item>) { if (exact_size_hint() > 0u) { return next_iter_.next_back(); } else { return Option<Item>(); } } usize exact_size_hint() const noexcept { return next_iter_.exact_size_hint().saturating_sub(skip_); } private: template <class U, class V> friend class IteratorBase; static Skip with(usize n, InnerSizedIter&& next_iter) noexcept { return Skip(n, ::sus::move(next_iter)); } Skip(usize n, InnerSizedIter&& next_iter) noexcept : skip_(n), next_iter_(::sus::move(next_iter)) {} usize skip_; InnerSizedIter next_iter_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(skip_), decltype(next_iter_)>; }; } namespace sus::iter { using ::sus::mem::relocate_by_memcpy; template <class InnerSizedIter> class [[nodiscard]] SkipWhile final : public IteratorBase<SkipWhile<InnerSizedIter>, typename InnerSizedIter::Item> { using Pred = ::sus::fn::FnMutBox<bool( const std::remove_reference_t<typename InnerSizedIter::Item>&)>; public: using Item = InnerSizedIter::Item; SkipWhile clone() const noexcept requires(::sus::mem::Clone<Pred> && ::sus::mem::Clone<InnerSizedIter>) { return SkipWhile(::sus::clone(pred_), ::sus::clone(next_iter_)); } Option<Item> next() noexcept { while (true) { Option<Item> out = next_iter_.next(); if (out.is_none() || pred_.is_none()) return out; if (!::sus::fn::call_mut( pred_.as_value_unchecked_mut(::sus::marker::unsafe_fn), out.as_value_unchecked(::sus::marker::unsafe_fn))) { pred_ = Option<Pred>(); return out; } } } SizeHint size_hint() const noexcept { return {0u, next_iter_.size_hint().upper}; } private: template <class U, class V> friend class IteratorBase; static SkipWhile with(Pred&& pred, InnerSizedIter&& next_iter) noexcept { return SkipWhile(::sus::move(pred), ::sus::move(next_iter)); } SkipWhile(Pred&& pred, InnerSizedIter&& next_iter) noexcept : pred_(Option<Pred>::with(::sus::move(pred))), next_iter_(::sus::move(next_iter)) {} Option<Pred> pred_; InnerSizedIter next_iter_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(pred_), decltype(next_iter_)>; }; } namespace sus::iter { using ::sus::mem::relocate_by_memcpy; template <class InnerSizedIter> class [[nodiscard]] StepBy final : public IteratorBase<StepBy<InnerSizedIter>, typename InnerSizedIter::Item> { public: using Item = InnerSizedIter::Item; StepBy clone() const noexcept requires(::sus::mem::Clone<InnerSizedIter>) { return StepBy(step_, ::sus::clone(next_iter_), first_take_); } Option<Item> next() noexcept { Option<Item> out = next_iter_.next(); if (first_take_) { first_take_ = false; } else { for (usize i; i < step_; i += 1u) { if (out.is_none()) return out; out = next_iter_.next(); } } return out; } SizeHint size_hint() const noexcept { auto first_size = [this](usize n) { if (n == 0u) { return 0_usize; } else { return 1u + (n - 1u) / (step_ + 1u); } }; auto other_size = [this](usize n) { return n / (step_ + 1u); }; auto [lower, upper] = next_iter_.size_hint(); if (first_take_) { return {first_size(lower), upper.map(first_size)}; } else { return {other_size(lower), upper.map(other_size)}; } } Option<Item> next_back() noexcept requires(DoubleEndedIterator<InnerSizedIter, Item> && ExactSizeIterator<InnerSizedIter, Item>) { const usize n = next_back_index(); Option<Item> out = next_iter_.next_back(); for (usize i; i < n; i += 1u) { if (out.is_none()) return out; out = next_iter_.next_back(); } return out; } usize exact_size_hint() const noexcept requires(ExactSizeIterator<InnerSizedIter, Item>) { return size_hint().lower; } template <class U, class V> friend class IteratorBase; usize next_back_index() const requires(ExactSizeIterator<InnerSizedIter, Item>) { auto rem = next_iter_.exact_size_hint() % (step_ + 1u); if (first_take_) return rem == 0u ? step_ : rem - 1u; else return rem; } static StepBy with(usize step, InnerSizedIter&& next_iter) noexcept { return StepBy(step - 1u, ::sus::move(next_iter), true); } StepBy(usize step, InnerSizedIter&& next_iter, bool first_take) noexcept : step_(step), next_iter_(::sus::move(next_iter)), first_take_(first_take) {} usize step_; InnerSizedIter next_iter_; bool first_take_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(step_), decltype(next_iter_), decltype(first_take_)>; }; } namespace sus::iter { using ::sus::mem::relocate_by_memcpy; template <class InnerSizedIter> class [[nodiscard]] Take final : public IteratorBase<Take<InnerSizedIter>, typename InnerSizedIter::Item> { public: using Item = InnerSizedIter::Item; Take(Take&&) = default; Take& operator=(Take&&) = default; constexpr Take clone() const noexcept requires(::sus::mem::Clone<InnerSizedIter>) { return Take(n_, ::sus::clone(next_iter_)); } constexpr Option<Item> next() noexcept { if (n_ != 0u) { n_ -= 1u; return next_iter_.next(); } else { return Option<Item>(); } } constexpr SizeHint size_hint() const noexcept { if (n_ == 0u) { return {0u, ::sus::some(0u)}; } auto [lower, upper] = next_iter_.size_hint(); lower = ::sus::ops::min(lower, n_); upper = ::sus::move(upper) .map([this](usize upper) { return ::sus::ops::min(upper, n_); }) .or_else([this] { return ::sus::some(n_); }); return {lower, upper}; } constexpr Option<Item> next_back() noexcept requires(DoubleEndedIterator<InnerSizedIter, Item> && ExactSizeIterator<InnerSizedIter, Item>) { if (n_ == 0u) { return Option<Item>(); } else { usize skip = next_iter_.exact_size_hint().saturating_sub(n_); n_ -= 1u; while (true) { if (skip == 0u) return next_iter_.next_back(); if (next_iter_.next_back().is_none()) return Option<Item>(); skip -= 1u; } } } constexpr usize exact_size_hint() const noexcept { return ::sus::ops::min(next_iter_.exact_size_hint(), n_); } private: template <class U, class V> friend class IteratorBase; static constexpr Take with(usize n, InnerSizedIter&& next_iter) noexcept { return Take(n, ::sus::move(next_iter)); } constexpr Take(usize n, InnerSizedIter&& next_iter) noexcept : n_(n), next_iter_(::sus::move(next_iter)) {} usize n_; InnerSizedIter next_iter_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(n_), decltype(next_iter_)>; }; } namespace sus::iter { using ::sus::mem::relocate_by_memcpy; template <class InnerSizedIter, class Pred> class [[nodiscard]] TakeWhile final : public IteratorBase<TakeWhile<InnerSizedIter, Pred>, typename InnerSizedIter::Item> { using ConstRefItem = const std::remove_reference_t<typename InnerSizedIter::Item>&; static_assert(::sus::fn::FnMut<Pred, bool(ConstRefItem)>); public: using Item = InnerSizedIter::Item; constexpr TakeWhile clone() const noexcept requires(::sus::mem::Clone<InnerSizedIter>) { return TakeWhile(::sus::clone(pred_), ::sus::clone(next_iter_)); } constexpr Option<Item> next() noexcept { Option<Item> out; if (pred_.is_none()) return out; out = next_iter_.next(); if (out.is_none()) return out; if (!::sus::fn::call_mut( pred_.as_value_unchecked_mut(::sus::marker::unsafe_fn), out.as_value_unchecked(::sus::marker::unsafe_fn))) { pred_ = Option<Pred>(); out = Option<Item>(); } return out; } constexpr SizeHint size_hint() const noexcept { if (pred_.is_none()) return {0u, sus::some(0u)}; return {0u, next_iter_.size_hint().upper}; } private: template <class U, class V> friend class IteratorBase; static constexpr TakeWhile with(Pred&& pred, InnerSizedIter&& next_iter) noexcept { return TakeWhile(::sus::move(pred), ::sus::move(next_iter)); } constexpr TakeWhile(Pred&& pred, InnerSizedIter&& next_iter) noexcept : pred_(::sus::some(::sus::move(pred))), next_iter_(::sus::move(next_iter)) {} ::sus::Option<Pred> pred_; InnerSizedIter next_iter_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(pred_), decltype(next_iter_)>; }; } namespace sus::iter { using ::sus::mem::relocate_by_memcpy; namespace __private { template <class T> using GetItem = typename T::Item; template <class Item, size_t N, class... T> inline constexpr Option<Item> nexts(auto& iters, T&&... args) { constexpr size_t I = sizeof...(T); if constexpr (I == N) { if ((... && args.is_some())) { return Option<Item>::with(Item::with( ::sus::move(args).unwrap_unchecked(::sus::marker::unsafe_fn)...)); } else { return Option<Item>(); } } else { return nexts<Item, N>(iters, ::sus::move(args)..., iters.template at_mut<I>().next()); } } template <size_t I, size_t N> inline constexpr SizeHint size_hints(auto& iters) noexcept { if constexpr (I == N - 1) { return iters.template at<I>().size_hint(); } else { SizeHint left = iters.template at<I>().size_hint(); SizeHint right = size_hints<I + 1, N>(iters); usize lower = ::sus::ops::min(left.lower, right.lower); if (left.upper.is_some() && right.upper.is_some()) { usize lu = left.upper.as_value(); usize ru = right.upper.as_value(); return SizeHint(lower, ::sus::some(::sus::ops::min(lu, ru))); } else if (left.upper.is_some()) { return SizeHint(lower, left.upper); } else if (right.upper.is_some()) { return SizeHint(lower, right.upper); } else { return SizeHint(lower, sus::none()); } } } template <size_t I, size_t N> inline constexpr usize exact_size_hints(auto& iters) noexcept { if constexpr (I == N - 1) { return iters.template at<I>().exact_size_hint(); } else { usize left = iters.template at<I>().exact_size_hint(); usize right = exact_size_hints<I + 1, N>(iters); return ::sus::ops::min(left, right); } } } template <class... InnerSizedIters> class [[nodiscard]] Zip final : public IteratorBase<Zip<InnerSizedIters...>, sus::Tuple<__private::GetItem<InnerSizedIters>...>> { public: using Item = sus::Tuple<__private::GetItem<InnerSizedIters>...>; constexpr Zip(Zip&&) = default; Zip& operator=(Zip&&) = default; constexpr Zip clone() const noexcept requires((... && ::sus::mem::Clone<InnerSizedIters>)) { return Zip(::sus::clone(iters_)); } constexpr Option<Item> next() noexcept { return __private::nexts<Item, sizeof...(InnerSizedIters)>(iters_); } constexpr SizeHint size_hint() const noexcept { return __private::size_hints<0, sizeof...(InnerSizedIters)>(iters_); } constexpr usize exact_size_hint() const noexcept requires( (... && ExactSizeIterator<InnerSizedIters, typename InnerSizedIters::Item>)) { return __private::exact_size_hints<0, sizeof...(InnerSizedIters)>(iters_); } private: template <class U, class V> friend class IteratorBase; static constexpr Zip with(sus::Tuple<InnerSizedIters...>&& iters) noexcept { return Zip(::sus::move(iters)); } constexpr Zip(::sus::Tuple<InnerSizedIters...>&& iters) noexcept : iters_(::sus::move(iters)) {} ::sus::Tuple<InnerSizedIters...> iters_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(iters_)>; }; } namespace sus::containers::__private { template <class... Ts> struct VecMarker { constexpr inline VecMarker(::sus::tuple_type::Tuple<Ts&&...>&& values) : values(::sus::move(values)){}; ::sus::tuple_type::Tuple<Ts&&...> values; template <class U> requires((... && std::constructible_from<U, Ts &&>)) inline constexpr operator Vec<U>() && noexcept { auto v = Vec<U>::with_capacity(sizeof...(Ts)); auto push_elements = [&, this]<size_t... Is>(std::integer_sequence<size_t, Is...>) { (v.push(::sus::forward<Ts>(values.template at_mut<Is>())), ...); }; push_elements(std::make_integer_sequence<size_t, sizeof...(Ts)>()); return v; } template <class U> requires((... && std::constructible_from<U, Ts &&>)) inline constexpr Vec<U> construct() && noexcept { return ::sus::move(*this); } template <int&..., class U = ::sus::choice_type::__private::PackFirst<Ts...>> requires(... && std::same_as<U, Ts>) inline constexpr Vec<U> construct() && noexcept { return ::sus::move(*this); } }; } namespace sus::containers { template <class ItemT> struct [[nodiscard]] Drain final : public ::sus::iter::IteratorBase<Drain<ItemT>, ItemT> { public: using Item = ItemT; public: constexpr Drain(Drain&& rhs) noexcept : tail_start_(rhs.tail_start_), tail_len_(rhs.tail_len_), original_vec_(::sus::move(rhs.original_vec_)), vec_(::sus::move(rhs.vec_)), iter_(rhs.iter_.take()) {} constexpr Drain& operator=(Drain&&) noexcept { ::sus::panic(); } ~Drain() noexcept { if (iter_.is_some()) { restore_vec(0u); } } void keep_rest() && noexcept { const usize unyielded_len = iter_->exact_size_hint(); Item* const unyielded_ptr = iter_.take().unwrap().as_mut_slice().as_mut_ptr(); const usize start = vec_.len(); Item* const start_ptr = vec_.as_mut_ptr() + start; if (unyielded_ptr != start_ptr) { Item* const src = unyielded_ptr; Item* const dst = start_ptr; if constexpr (::sus::mem::relocate_by_memcpy<Item>) { if (unyielded_len > 0u) { ::sus::ptr::copy(::sus::marker::unsafe_fn, src, dst, unyielded_len); } } else { for (usize i; i < unyielded_len; i += 1u) { *(dst + i) = ::sus::move(*(src + i)); } } } restore_vec(unyielded_len); } Option<Item> next() noexcept { return iter_->next().map([](Item& i) { return sus::move(i); }); } Option<Item> next_back() noexcept { return iter_->next_back().map([](Item& i) { return sus::move(i); }); } ::sus::iter::SizeHint size_hint() const noexcept { return iter_->size_hint(); } ::sus::num::usize exact_size_hint() const noexcept { return iter_->exact_size_hint(); } private: template <class VecT> friend class Vec; void restore_vec(usize kept) { const usize start = vec_.len() + kept; const usize tail = tail_start_; if (start != tail) { const usize drop_len = tail - start; Item* const src = vec_.as_mut_ptr() + tail; Item* const dst = vec_.as_mut_ptr() + start; if constexpr (::sus::mem::relocate_by_memcpy<Item>) { if (tail_len_ > 0u) { ::sus::ptr::copy(::sus::marker::unsafe_fn, src, dst, tail_len_); } } else { usize i; for (; i < tail_len_; i += 1u) { *(dst + i) = ::sus::move(*(src + i)); } for (; i < tail_len_ + drop_len; i += 1u) { (dst + i)->~Item(); } } } vec_.set_len(::sus::marker::unsafe_fn, start + tail_len_); original_vec_.as_mut() = ::sus::move(vec_); } static constexpr auto with(Vec<Item>&& vec, ::sus::ops::Range<usize> range) noexcept { return Drain(::sus::move(vec), range); } constexpr Drain(Vec<Item>&& vec, ::sus::ops::Range<usize> range) noexcept : tail_start_(range.finish), tail_len_(vec.len() - range.finish), vec_(::sus::move(vec)), original_vec_(sus::mref_into(vec)) { auto slice = vec_.get_range_mut(range).unwrap(); slice.drop_iterator_invalidation_tracking(::sus::marker::unsafe_fn); iter_ = ::sus::some(::sus::move(slice).iter_mut()); vec_.set_len(::sus::marker::unsafe_fn, range.start); } usize tail_start_; usize tail_len_; sus::ptr::NonNull<Vec<Item>> original_vec_; Vec<Item> vec_; Option<SliceIterMut<Item&>> iter_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(tail_start_), decltype(tail_len_), decltype(vec_), decltype(tail_start_), decltype(original_vec_)>; static_assert(SusUnsafeTrivialRelocate, "Type is not trivially relocatable"); }; } namespace sus::containers { template <class ItemT> struct [[nodiscard]] VecIntoIter final : public ::sus::iter::IteratorBase<VecIntoIter<ItemT>, ItemT> { public: using Item = ItemT; static constexpr auto with(Vec<Item>&& vec) noexcept { return VecIntoIter(::sus::move(vec)); } constexpr VecIntoIter clone() const noexcept requires(::sus::mem::Clone<Item>) { return VecIntoIter(::sus::clone(vec_), front_index_, back_index_); } constexpr Option<Item> next() noexcept { if (front_index_ == back_index_) [[unlikely]] return Option<Item>(); Item& item = vec_.get_unchecked_mut( ::sus::marker::unsafe_fn, ::sus::mem::replace(front_index_, front_index_ + 1_usize)); return Option<Item>::with(move(item)); } constexpr Option<Item> next_back() noexcept { if (front_index_ == back_index_) [[unlikely]] return Option<Item>(); back_index_ -= 1u; Item& item = vec_.get_unchecked_mut(::sus::marker::unsafe_fn, back_index_); return Option<Item>::with(move(item)); } constexpr ::sus::iter::SizeHint size_hint() const noexcept { const usize remaining = back_index_ - front_index_; return ::sus::iter::SizeHint( remaining, ::sus::Option<::sus::num::usize>::with(remaining)); } constexpr ::sus::num::usize exact_size_hint() const noexcept { return back_index_ - front_index_; } private: constexpr VecIntoIter(Vec<Item>&& vec) noexcept : vec_(::sus::move(vec)) {} constexpr VecIntoIter(Vec<Item>&& vec, usize front, usize back) noexcept : vec_(::sus::move(vec)), front_index_(front), back_index_(back) {} Vec<Item> vec_; usize front_index_ = 0_usize; usize back_index_ = vec_.len(); static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(front_index_), decltype(back_index_), decltype(vec_)>; static_assert(SusUnsafeTrivialRelocate, "Type is not trivially relocatable"); }; } namespace sus::containers { template <class T> class Vec final { static_assert( !std::is_reference_v<T>, "Vec<T&> is invalid as Vec must hold value types. Use Vec<T*> instead."); static_assert(!std::is_const_v<T>, "`Vec<const T>` should be written `const Vec<T>`, as const " "applies transitively."); public: inline constexpr Vec() noexcept : Vec(nullptr, 0_usize, 0_usize) {} __attribute__((pure)) static inline constexpr Vec with_capacity(usize capacity) noexcept { check(::sus::mem::size_of<T>() * capacity <= ::sus::mog<usize>(isize::MAX)); auto v = Vec(nullptr, 0_usize, 0_usize); v.grow_to_exact(capacity); return v; } template <std::convertible_to<T>... Ts> static inline constexpr Vec with(Ts&&... values) noexcept { auto v = Vec::with_capacity(sizeof...(Ts)); (..., v.push(::sus::forward<Ts>(values))); return v; } __attribute__((pure)) static constexpr Vec from_raw_parts(::sus::marker::UnsafeFnMarker, T* ptr, usize length, usize capacity) noexcept { return Vec(ptr, length, capacity); } static constexpr Vec from(::sus::Slice<T> slice) noexcept requires(sus::mem::Clone<T>) { auto v = Vec::with_capacity(slice.len()); for (const T& t : slice) v.push(::sus::clone(t)); return v; } static constexpr Vec from(::sus::SliceMut<T> slice) noexcept requires(sus::mem::Clone<T>) { auto v = Vec::with_capacity(slice.len()); for (const T& t : slice) v.push(::sus::clone(t)); return v; } template <class C, size_t N> requires(std::same_as<T, u8> && (std::same_as<C, char> || std::same_as<C, signed char> || std::same_as<C, unsigned char>) && N <= ::sus::mog<usize>(isize::MAX)) static constexpr Vec from(const C (&arr)[N]) { auto s = sus::Slice<C>::from(arr); auto v = Vec::with_capacity(N - 1); for (auto c : s[sus::ops::RangeTo<usize>(N - 1)]) v.push(sus::mog<uint8_t>(c)); ::sus::check(s[N - 1] == 0); return v; } constexpr ~Vec() { if (is_alloced()) free_storage(); } constexpr Vec(Vec&& o) noexcept : slice_mut_( o.slice_mut_.slice_.iter_refs_.take_for_owner(), ::sus::mem::replace(o.raw_data(), nullptr), ::sus::mem::replace(o.slice_mut_.slice_.len_, kMovedFromLen)), capacity_(::sus::mem::replace(o.capacity_, kMovedFromCapacity)) { check(!is_moved_from()); check(!has_iterators()); } constexpr Vec& operator=(Vec&& o) noexcept { check(!o.is_moved_from()); check(!has_iterators()); check(!o.has_iterators()); if (is_alloced()) free_storage(); raw_data() = ::sus::mem::replace(o.raw_data(), nullptr); slice_mut_.slice_.len_ = ::sus::mem::replace(o.slice_mut_.slice_.len_, kMovedFromLen); slice_mut_.slice_.iter_refs_ = o.slice_mut_.slice_.iter_refs_.take_for_owner(); capacity_ = ::sus::mem::replace(o.capacity_, kMovedFromCapacity); return *this; } constexpr Vec clone() const& noexcept requires(::sus::mem::Clone<T>) { check(!is_moved_from()); auto v = Vec::with_capacity(capacity_); const auto self_len = len(); for (auto i = size_t{0}; i < self_len; ++i) { std::construct_at( v.raw_data() + i, ::sus::clone(get_unchecked(::sus::marker::unsafe_fn, i))); } v.set_len(::sus::marker::unsafe_fn, self_len); return v; } constexpr void clone_from(const Vec& source) & noexcept requires(::sus::mem::Clone<T>) { check(!is_moved_from()); check(!source.is_moved_from()); check(!has_iterators()); if (&source == this) [[unlikely]] return; if (source.capacity_ == 0_usize) { destroy_storage_objects(); free_storage(); raw_data() = nullptr; set_len(::sus::marker::unsafe_fn, 0_usize); capacity_ = 0_usize; } else { grow_to_exact(source.capacity_); const size_t self_len = size_t{len()}; const size_t source_len = size_t{source.len()}; const size_t in_place_count = sus::ops::min(self_len, source_len); for (auto i = size_t{0}; i < in_place_count; ++i) { ::sus::clone_into(*(raw_data() + i), *(source.raw_data() + i)); } for (auto i = in_place_count; i < self_len; i += 1u) { get_unchecked_mut(::sus::marker::unsafe_fn, i).~T(); } for (auto i = in_place_count; i < source_len; i += 1u) { std::construct_at( raw_data() + i, ::sus::clone(source.get_unchecked(::sus::marker::unsafe_fn, i))); } set_len(::sus::marker::unsafe_fn, source_len); } } constexpr Drain<T> drain(::sus::ops::RangeBounds<usize> auto range) noexcept { check(!is_moved_from()); check(!has_iterators()); ::sus::ops::Range<usize> bounded_range = range.start_at(range.start_bound().unwrap_or(0u)) .end_at(range.end_bound().unwrap_or(len())); return Drain<T>::with(::sus::move(*this), bounded_range); } constexpr ::sus::Tuple<T*, usize, usize> into_raw_parts() && noexcept { check(!is_moved_from()); check(!has_iterators()); return sus::tuple( ::sus::mem::replace(raw_data(), nullptr), ::sus::mem::replace(slice_mut_.slice_.len_, kMovedFromLen), ::sus::mem::replace(capacity_, kMovedFromCapacity)); } __attribute__((pure)) constexpr inline usize capacity() const& noexcept { check(!is_moved_from()); return capacity_; } constexpr void clear() noexcept { check(!is_moved_from()); check(!has_iterators()); destroy_storage_objects(); set_len(::sus::marker::unsafe_fn, 0_usize); } constexpr void extend(sus::iter::IntoIterator<const T&> auto&& ii) noexcept requires(sus::mem::Copy<T> && ::sus::mem::IsMoveRef<decltype(ii)>) { check(!is_moved_from()); check(!has_iterators()); auto&& it = sus::move(ii).into_iter(); reserve(it.size_hint().lower); for (const T& v : ::sus::move(it)) { push(v); } } constexpr void extend(sus::iter::IntoIterator<T> auto&& ii) noexcept requires(::sus::mem::IsMoveRef<decltype(ii)>) { check(!is_moved_from()); check(!has_iterators()); auto&& it = sus::move(ii).into_iter(); reserve(it.size_hint().lower); for (T&& v : ::sus::move(it)) { push(::sus::move(v)); } } constexpr void extend_from_slice(::sus::containers::Slice<T> s) noexcept requires(sus::mem::Clone<T>) { check(!is_moved_from()); check(!has_iterators()); if (s.is_empty()) { return; } const auto self_len = len(); const auto slice_len = s.len(); const T* slice_ptr = s.as_ptr(); if (is_alloced()) { const T* vec_ptr = raw_data(); ::sus::check(!(slice_ptr >= vec_ptr && slice_ptr <= vec_ptr + self_len)); } reserve(slice_len); if constexpr (sus::mem::TrivialCopy<T>) { ::sus::ptr::copy_nonoverlapping(::sus::marker::unsafe_fn, slice_ptr, raw_data() + self_len, slice_len); set_len(::sus::marker::unsafe_fn, self_len + slice_len); } else { for (const T& t : s) push(::sus::clone(t)); } } constexpr void grow_to_exact(usize cap) noexcept { check(!is_moved_from()); check(!has_iterators()); if (cap <= capacity_) return; const auto bytes = ::sus::mem::size_of<T>() * cap; check(bytes <= ::sus::mog<usize>(isize::MAX)); if (!is_alloced()) { raw_data() = std::allocator<T>().allocate(size_t{cap}); capacity_ = cap; return; } T* new_allocation = std::allocator<T>().allocate(size_t{cap}); T* old_t = raw_data(); T* new_t = new_allocation; if constexpr (::sus::mem::relocate_by_memcpy<T>) { if (!std::is_constant_evaluated()) { ::sus::ptr::copy_nonoverlapping(::sus::marker::unsafe_fn, old_t, new_t, capacity_); std::allocator<T>().deallocate(raw_data(), size_t{capacity_}); raw_data() = new_allocation; capacity_ = cap; return; } } const ::sus::num::usize self_len = len(); for (::sus::num::usize i; i < self_len; i += 1u) { std::construct_at(new_t, ::sus::move(*old_t)); old_t->~T(); ++old_t; ++new_t; } std::allocator<T>().deallocate(raw_data(), size_t{capacity_}); raw_data() = new_allocation; capacity_ = cap; } constexpr void reserve(usize additional) noexcept { check(!is_moved_from()); check(!has_iterators()); if (len() + additional <= capacity_) return; grow_to_exact(apply_growth_function(additional)); } constexpr void reserve_exact(usize additional) noexcept { check(!is_moved_from()); check(!has_iterators()); const usize cap = len() + additional; if (cap <= capacity_) return; grow_to_exact(cap); } constexpr void set_len(::sus::marker::UnsafeFnMarker, usize new_len) { check(!is_moved_from()); ::sus::check(new_len <= capacity_); slice_mut_.slice_.len_ = new_len; } constexpr Option<T> pop() noexcept { check(!is_moved_from()); check(!has_iterators()); const auto self_len = len(); if (self_len > 0u) { auto o = Option<T>::with(sus::move( get_unchecked_mut(::sus::marker::unsafe_fn, self_len - 1u))); get_unchecked_mut(::sus::marker::unsafe_fn, self_len - 1u).~T(); set_len(::sus::marker::unsafe_fn, self_len - 1u); return o; } else { return Option<T>(); } } constexpr void push(T t) noexcept requires(::sus::mem::Move<T>) { check(!is_moved_from()); check(!has_iterators()); reserve(1_usize); const auto self_len = len(); std::construct_at(raw_data() + self_len, ::sus::move(t)); set_len(::sus::marker::unsafe_fn, self_len + 1_usize); } template <class... Us> constexpr void emplace(Us&&... args) noexcept requires(::sus::mem::Move<T> && !(sizeof...(Us) == 1u && (... && std::same_as<std::decay_t<T>, std::decay_t<Us>>))) { check(!is_moved_from()); check(!has_iterators()); reserve(1_usize); const auto self_len = len(); std::construct_at(raw_data() + self_len, ::sus::forward<Us>(args)...); set_len(::sus::marker::unsafe_fn, self_len + 1_usize); } __attribute__((pure)) constexpr Slice<T> as_slice() const& noexcept { return *this; } constexpr Slice<T> as_slice() && = delete; __attribute__((pure)) constexpr SliceMut<T> as_mut_slice() & noexcept { return *this; } constexpr VecIntoIter<T> into_iter() && noexcept requires(::sus::mem::Move<T>) { check(!is_moved_from()); return VecIntoIter<T>::with(::sus::move(*this)); } template <class U> requires(::sus::ops::Eq<T, U>) friend constexpr bool operator==(const Vec<T>& l, const Vec<U>& r) noexcept { return l.as_slice() == r.as_slice(); } template <class U> requires(!::sus::ops::Eq<T, U>) friend constexpr bool operator==(const Vec<T>& l, const Vec<U>& r) = delete; template <class U> requires(::sus::ops::Eq<T, U>) friend constexpr bool operator==(const Vec<T>& l, const Slice<U>& r) noexcept { return l.as_slice() == r; } template <class U> requires(::sus::ops::Eq<T, U>) friend constexpr bool operator==(const Vec<T>& l, const SliceMut<U>& r) noexcept { return l.as_slice() == r.as_slice(); } __attribute__((pure)) constexpr const T& operator[](::sus::num::usize i) const& noexcept { ::sus::check(i < len()); return *(as_ptr() + i); } constexpr const T& operator[](::sus::num::usize i) && = delete; __attribute__((pure)) constexpr T& operator[](::sus::num::usize i) & noexcept { check(i < len()); return *(as_mut_ptr() + i); } __attribute__((pure)) constexpr Slice<T> operator[]( const ::sus::ops::RangeBounds<::sus::num::usize> auto range) const& noexcept { const ::sus::num::usize length = len(); const ::sus::num::usize rstart = range.start_bound().unwrap_or(0u); const ::sus::num::usize rend = range.end_bound().unwrap_or(length); const ::sus::num::usize rlen = rend >= rstart ? rend - rstart : 0u; ::sus::check(rlen <= length); ::sus::check(rstart <= length && rstart <= length - rlen); return Slice<T>::from_raw_parts( ::sus::marker::unsafe_fn, slice_mut_.slice_.iter_refs_.to_view_from_owner(), as_ptr() + rstart, rlen); } constexpr Slice<T> operator[]( const ::sus::ops::RangeBounds<::sus::num::usize> auto range) && = delete; __attribute__((pure)) constexpr SliceMut<T> operator[]( const ::sus::ops::RangeBounds<::sus::num::usize> auto range) & noexcept { const ::sus::num::usize length = len(); const ::sus::num::usize rstart = range.start_bound().unwrap_or(0u); const ::sus::num::usize rend = range.end_bound().unwrap_or(length); const ::sus::num::usize rlen = rend >= rstart ? rend - rstart : 0u; ::sus::check(rlen <= length); ::sus::check(rstart <= length && rstart <= length - rlen); return SliceMut<T>::from_raw_parts_mut( ::sus::marker::unsafe_fn, slice_mut_.slice_.iter_refs_.to_view_from_owner(), as_mut_ptr() + rstart, rlen); } __attribute__((pure)) constexpr operator const Slice<T>&() const& noexcept { check(!is_moved_from()); return slice_mut_.slice_; } __attribute__((pure)) constexpr operator const Slice<T>&() && = delete; __attribute__((pure)) constexpr operator Slice<T>&() & noexcept { check(!is_moved_from()); return slice_mut_.slice_; } __attribute__((pure)) constexpr operator SliceMut<T>&() & noexcept { check(!is_moved_from()); return slice_mut_; } __attribute__((pure)) constexpr inline bool is_empty() const& noexcept { return len() == 0u; } __attribute__((pure)) constexpr inline ::sus::num::usize len() const& noexcept { return slice_mut_.slice_.len_; } __attribute__((pure)) constexpr inline const T* as_ptr() const& noexcept { return slice_mut_.slice_.data_; } constexpr inline const T* as_ptr() && = delete; __attribute__((pure)) constexpr ::sus::ops::Range<const T*> as_ptr_range() const& noexcept { return ::sus::ops::Range<const T*>(as_ptr(), as_ptr() + len()); } constexpr ::sus::ops::Range<const T*> as_ptr_range() && = delete; constexpr ::sus::result::Result<::sus::num::usize, ::sus::num::usize> binary_search(const T& x) const& noexcept requires(::sus::ops::Ord<T>) { return binary_search_by( [&x](const T& p) -> std::strong_ordering { return p <=> x; }); } constexpr ::sus::result::Result<::sus::num::usize, ::sus::num::usize> binary_search_by( ::sus::fn::FnMutRef<std::strong_ordering(const T&)> f) const& noexcept requires(::sus::ops::Ord<T>) { using Result = ::sus::result::Result<::sus::num::usize, ::sus::num::usize>; ::sus::num::usize size = len(); ::sus::num::usize left = 0u; ::sus::num::usize right = size; while (left < right) { auto mid = left + size / 2u; auto cmp = ::sus::fn::call_mut(f, get_unchecked(::sus::marker::unsafe_fn, mid)); if (cmp == std::strong_ordering::less) { left = mid + 1u; } else if (cmp == std::strong_ordering::greater) { right = mid; } else { static_assert(std::same_as<std::decay_t<decltype(::sus::marker::unsafe_fn)>, ::sus::marker::UnsafeFnMarker>); #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wassume" __builtin_assume(mid.primitive_value < slice_mut_.slice_.len_.primitive_value) #pragma clang diagnostic pop ; return Result::with(mid); } size = right - left; } static_assert(std::same_as<std::decay_t<decltype(::sus::marker::unsafe_fn)>, ::sus::marker::UnsafeFnMarker>); #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wassume" __builtin_assume(left.primitive_value <= slice_mut_.slice_.len_.primitive_value) #pragma clang diagnostic pop ; return Result::with_err(left); } template <::sus::ops::Ord Key> ::sus::result:: Result<::sus::num::usize, ::sus::num::usize> constexpr binary_search_by_key( const Key& key, ::sus::fn::FnMut<Key(const T&)> auto&& f) const& noexcept { return binary_search_by([&key, &f](const T& p) -> std::strong_ordering { return ::sus::fn::call_mut(f, p) <=> key; }); } constexpr Chunks<T> chunks(::sus::num::usize chunk_size) const& noexcept { return Chunks<T>::with(slice_mut_.slice_.iter_refs_.to_iter_from_owner(), *this, chunk_size); } constexpr Chunks<T> chunks(::sus::num::usize chunk_size) && = delete; constexpr ChunksExact<T> chunks_exact( ::sus::num::usize chunk_size) const& noexcept { return ChunksExact<T>::with(slice_mut_.slice_.iter_refs_.to_iter_from_owner(), *this, chunk_size); } constexpr ChunksExact<T> chunks_exact(::sus::num::usize chunk_size) && = delete; using ConcatOutputType = ::sus::containers::Vec<T>; constexpr auto concat() const& noexcept requires(::sus::containers::Concat<T>) { const auto length = len(); ::sus::num::usize cap; for (::sus::num::usize i; i < length; i += 1u) { cap += get_unchecked(::sus::marker::unsafe_fn, i).len(); } using Container = typename T::ConcatOutputType; auto out = Container::with_capacity(cap); for (::sus::num::usize i; i < length; i += 1u) { get_unchecked(::sus::marker::unsafe_fn, i).concat_into(out); } return out; } constexpr void concat_into(::sus::containers::Vec<T>& vec) const& noexcept requires(::sus::mem::Clone<T>) { vec.extend_from_slice(*this); } constexpr bool contains(const T& x) const& noexcept requires(::sus::ops::Eq<T>) { const auto length = len(); const auto* const p = as_ptr(); for (::sus::num::usize i; i < length; i += 1u) { if (*(p + i) == x) return true; } return false; } constexpr bool ends_with(const Slice<T>& suffix) const& noexcept requires(::sus::ops::Eq<T>) { const auto m = len(); const auto n = suffix.len(); return m >= n && suffix == (*this)[::sus::ops::RangeFrom(m - n)]; } __attribute__((pure)) constexpr ::sus::Option<const T&> first() const& noexcept { if (len() > 0u) { return ::sus::Option<const T&>::with( get_unchecked(::sus::marker::unsafe_fn, 0u)); } else { return ::sus::Option<const T&>(); } } constexpr ::sus::Option<const T&> first() && = delete; __attribute__((pure)) constexpr Option<const T&> get(::sus::num::usize i) const& noexcept { if (i < len()) [[likely]] return Option<const T&>::with(get_unchecked(::sus::marker::unsafe_fn, i)); else return Option<const T&>(); } constexpr Option<const T&> get(::sus::num::usize i) && = delete; __attribute__((pure)) constexpr inline const T& get_unchecked( ::sus::marker::UnsafeFnMarker, ::sus::num::usize i) const& noexcept { ::sus::check(i.primitive_value < slice_mut_.slice_.len_.primitive_value); return as_ptr()[size_t{i}]; } constexpr inline const T& get_unchecked(::sus::marker::UnsafeFnMarker, ::sus::num::usize i) && = delete; __attribute__((pure)) constexpr Option<Slice<T>> get_range( const ::sus::ops::RangeBounds<::sus::num::usize> auto range) const& noexcept { const ::sus::num::usize length = len(); const ::sus::num::usize rstart = range.start_bound().unwrap_or(0u); const ::sus::num::usize rend = range.end_bound().unwrap_or(length); const ::sus::num::usize rlen = rend >= rstart ? rend - rstart : 0u; if (rlen > length) return sus::none(); if (rstart > length || rstart > length - rlen) return sus::none(); return Option<Slice<T>>::with(Slice<T>::from_raw_parts( ::sus::marker::unsafe_fn, slice_mut_.slice_.iter_refs_.to_view_from_owner(), as_ptr() + rstart, rlen)); } constexpr Option<Slice<T>> get_range( const ::sus::ops::RangeBounds<::sus::num::usize> auto range) && = delete; __attribute__((pure)) constexpr Slice<T> get_range_unchecked( ::sus::marker::UnsafeFnMarker, const ::sus::ops::RangeBounds<::sus::num::usize> auto range) const& noexcept { const ::sus::num::usize rstart = range.start_bound().unwrap_or(0u); const ::sus::num::usize rend = range.end_bound().unwrap_or(len()); const ::sus::num::usize rlen = rend >= rstart ? rend - rstart : 0u; return Slice<T>::from_raw_parts( ::sus::marker::unsafe_fn, slice_mut_.slice_.iter_refs_.to_view_from_owner(), as_ptr() + rstart, rlen); } constexpr Slice<T> get_range_unchecked( ::sus::marker::UnsafeFnMarker, const ::sus::ops::RangeBounds<::sus::num::usize> auto range) && = delete; __attribute__((pure)) constexpr SliceIter<const T&> iter() const& noexcept { return SliceIter<const T&>::with(slice_mut_.slice_.iter_refs_.to_iter_from_owner(), as_ptr(), len()); } constexpr SliceIter<const T&> iter() && = delete; using JoinOutputType = ::sus::containers::Vec<T>; template <class Sep> constexpr auto join(const Sep& separator) const& noexcept requires(::sus::containers::Join<T, Sep>) { const auto length = len(); ::sus::num::usize cap; for (::sus::num::usize i; i < length; i += 1u) { cap += get_unchecked(::sus::marker::unsafe_fn, i).len(); } using Container = typename T::JoinOutputType; auto out = Container::with_capacity(cap); if (length > 0u) get_unchecked(::sus::marker::unsafe_fn, 0u).join_into(out); for (::sus::num::usize i = 1u; i < length; i += 1u) { T::join_sep_into(out, separator); get_unchecked(::sus::marker::unsafe_fn, i).join_into(out); } return out; } constexpr void join_into(::sus::containers::Vec<T>& vec) const& noexcept requires(::sus::mem::Clone<T>) { vec.extend_from_slice(*this); } static constexpr void join_sep_into(::sus::containers::Vec<T>& vec, const Slice<T>& separator) noexcept requires(::sus::mem::Clone<T>) { vec.extend_from_slice(separator); } static constexpr void join_sep_into(::sus::containers::Vec<T>& vec, const T& separator) noexcept requires(::sus::mem::Clone<T>) { vec.push(::sus::clone(separator)); } __attribute__((pure)) constexpr ::sus::Option<const T&> last() const& noexcept { const auto length = len(); if (length > 0u) return ::sus::Option<const T&>::with(*(as_ptr() + length - 1u)); else return ::sus::Option<const T&>(); } constexpr ::sus::Option<const T&> last() && = delete; constexpr ::sus::num::usize partition_point( ::sus::fn::FnMutRef<bool(const T&)> pred) const& noexcept { return binary_search_by([pred = ::sus::move(pred)](const T& x) { if (::sus::fn::call_mut(pred, x)) { return std::strong_ordering::less; } else { return std::strong_ordering::greater; } }) .unwrap_or_else([](::sus::num::usize i) { return i; }); } constexpr RChunks<T> rchunks(::sus::num::usize chunk_size) const& noexcept { return RChunks<T>::with(slice_mut_.slice_.iter_refs_.to_iter_from_owner(), *this, chunk_size); } constexpr RChunks<T> rchunks(::sus::num::usize chunk_size) && = delete; constexpr RChunksExact<T> rchunks_exact( ::sus::num::usize chunk_size) const& noexcept { return RChunksExact<T>::with(slice_mut_.slice_.iter_refs_.to_iter_from_owner(), *this, chunk_size); } constexpr RChunksExact<T> rchunks_exact(::sus::num::usize chunk_size) && = delete; constexpr ::sus::containers::Vec<T> repeat(usize n) const& noexcept requires(::sus::mem::TrivialCopy<T>) { auto buf = ::sus::containers::Vec<T>(); if (n == 0u) return buf; const usize l = len(); const usize capacity = l.saturating_mul(n); buf.reserve(capacity); buf.extend(iter()); { usize m = n >> 1u; while (m > 0u) { ::sus::ptr::copy_nonoverlapping(::sus::marker::unsafe_fn, buf.as_ptr(), buf.as_mut_ptr() + buf.len(), buf.len()); const usize buf_len = buf.len(); buf.set_len(::sus::marker::unsafe_fn, buf_len * 2u); m >>= 1u; } } const usize rem_len = capacity - buf.len(); if (rem_len > 0u) { ::sus::ptr::copy_nonoverlapping(::sus::marker::unsafe_fn, buf.as_ptr(), buf.as_mut_ptr() + buf.len(), rem_len); buf.set_len(::sus::marker::unsafe_fn, capacity); } return buf; } constexpr RSplit<T> rsplit( ::sus::fn::FnMutRef<bool(const T&)> pred) const& noexcept { return RSplit<T>::with( Split<T>::with(slice_mut_.slice_.iter_refs_.to_iter_from_owner(), *this, ::sus::move(pred))); } constexpr Split<T> rsplit(::sus::fn::FnMutRef<bool(const T&)>) && = delete; constexpr RSplitN<T> rsplitn( usize n, ::sus::fn::FnMutRef<bool(const T&)> pred) const& noexcept { return RSplitN<T>::with(RSplit<T>::with(Split<T>::with(slice_mut_.slice_.iter_refs_.to_iter_from_owner(), *this, ::sus::move(pred))), n); } constexpr RSplit<T> rsplitn( usize n, ::sus::fn::FnMutRef<bool(const T&)> pred) && = delete; constexpr Split<T> split( ::sus::fn::FnMutRef<bool(const T&)> pred) const& noexcept { return Split<T>::with(slice_mut_.slice_.iter_refs_.to_iter_from_owner(), *this, ::sus::move(pred)); } constexpr Split<T> split(::sus::fn::FnMutRef<bool(const T&)>) && = delete; __attribute__((pure)) constexpr ::sus::Tuple<Slice<T>, Slice<T>> split_at( ::sus::num::usize mid) const& noexcept { ::sus::check(mid <= len()); return split_at_unchecked(::sus::marker::unsafe_fn, mid); } constexpr ::sus::Tuple<Slice<T>, Slice<T>> split_at(::sus::num::usize mid) && = delete; __attribute__((pure)) constexpr ::sus::Tuple<Slice<T>, Slice<T>> split_at_unchecked( ::sus::marker::UnsafeFnMarker, ::sus::num::usize mid) const& noexcept { ::sus::check(mid.primitive_value <= slice_mut_.slice_.len_.primitive_value); const ::sus::num::usize rem = len().unchecked_sub(::sus::marker::unsafe_fn, mid); return ::sus::Tuple<Slice<T>, Slice<T>>::with( Slice<T>::from_raw_parts(::sus::marker::unsafe_fn, slice_mut_.slice_.iter_refs_.to_view_from_owner(), as_ptr(), mid), Slice<T>::from_raw_parts(::sus::marker::unsafe_fn, slice_mut_.slice_.iter_refs_.to_view_from_owner(), as_ptr() + mid, rem)); } constexpr ::sus::Tuple<Slice<T>, Slice<T>> split_at_unchecked( ::sus::marker::UnsafeFnMarker, ::sus::num::usize mid) && = delete; __attribute__((pure)) constexpr ::sus::Option<::sus::Tuple<const T&, Slice<T>>> split_first() const& noexcept { if (is_empty()) return ::sus::none(); return ::sus::some( ::sus::tuple(*as_ptr(), (*this)[::sus::ops::RangeFrom<usize>(1u)])); } constexpr ::sus::Option<::sus::Tuple<const T&, Slice<T>>> split_first() && = delete; constexpr SplitInclusive<T> split_inclusive( ::sus::fn::FnMutRef<bool(const T&)> pred) const& noexcept { return SplitInclusive<T>::with(slice_mut_.slice_.iter_refs_.to_iter_from_owner(), *this, ::sus::move(pred)); } constexpr SplitInclusive<T> split_inclusive( ::sus::fn::FnMutRef<bool(const T&)>) && = delete; __attribute__((pure)) constexpr ::sus::Option<::sus::Tuple<const T&, Slice<T>>> split_last() const& noexcept { if (is_empty()) return ::sus::none(); const usize last = len() - 1u; return ::sus::some(::sus::tuple(*(as_ptr() + last), (*this)[::sus::ops::RangeTo<usize>(last)])); } constexpr ::sus::Option<::sus::Tuple<const T&, Slice<T>>> split_last() && = delete; constexpr SplitN<T> splitn( usize n, ::sus::fn::FnMutRef<bool(const T&)> pred) const& noexcept { return SplitN<T>::with( Split<T>::with(slice_mut_.slice_.iter_refs_.to_iter_from_owner(), *this, ::sus::move(pred)), n); } constexpr Split<T> splitn(usize n, ::sus::fn::FnMutRef<bool(const T&)> pred) && = delete; constexpr bool starts_with(const Slice<T>& needle) const& requires(::sus::ops::Eq<T>) { const auto n = needle.len(); return len() >= n && needle == (*this)[::sus::ops::RangeTo(n)]; } constexpr ::sus::Option<Slice<T>> strip_prefix( const Slice<T>& prefix) const& noexcept requires(::sus::ops::Eq<T>) { const usize n = prefix.len(); if (n <= len()) { auto [head, tail] = split_at(n); if (head == prefix) { return ::sus::Option<Slice<T>>::with(tail); } } return ::sus::Option<Slice<T>>(); } constexpr ::sus::Option<Slice<T>> strip_prefix(const Slice<T>& prefix) const& = delete; constexpr ::sus::Option<Slice<T>> strip_suffix( const Slice<T>& suffix) const& noexcept requires(::sus::ops::Eq<T>) { const auto l = len(); const auto n = suffix.len(); if (n <= l) { auto [head, tail] = split_at(l - n); if (tail == suffix) { return ::sus::Option<Slice<T>>::with(head); } } return ::sus::Option<Slice<T>>(); } constexpr ::sus::Option<Slice<T>> strip_suffix(const Slice<T>& suffix) const& = delete; Vec<T> to_vec() const& noexcept requires(::sus::mem::Clone<T>); __attribute__((pure)) constexpr Windows<T> windows(usize size) const& noexcept { ::sus::check(size > 0u); return Windows<T>::with(slice_mut_.slice_.iter_refs_.to_iter_from_owner(), *this, size); } __attribute__((pure)) constexpr inline T* as_mut_ptr() & noexcept { return slice_mut_.slice_.data_; } __attribute__((pure)) constexpr ::sus::ops::Range<T*> as_mut_ptr_range() & noexcept { return ::sus::ops::Range<T*>(as_mut_ptr(), as_mut_ptr() + len()); } constexpr ChunksExactMut<T> chunks_exact_mut(::sus::num::usize chunk_size) & noexcept { return ChunksExactMut<T>::with(slice_mut_.slice_.iter_refs_.to_iter_from_owner(), *this, chunk_size); } constexpr ChunksMut<T> chunks_mut(::sus::num::usize chunk_size) & noexcept { return ChunksMut<T>::with(slice_mut_.slice_.iter_refs_.to_iter_from_owner(), *this, chunk_size); } constexpr void copy_from_slice(const Slice<T>& src) noexcept requires(::sus::mem::TrivialCopy<T>) { const ::sus::num::usize src_len = src.len(); const ::sus::num::usize dst_len = len(); ::sus::check(dst_len == src_len); const T* const src_ptr = src.as_ptr(); T* const dst_ptr = as_mut_ptr(); ::sus::check((src_ptr < dst_ptr && src_ptr <= dst_ptr - src_len) || (dst_ptr < src_ptr && dst_ptr <= src_ptr - dst_len)); if (std::is_constant_evaluated()) { for (::sus::num::usize i; i < dst_len; i += 1u) *(dst_ptr + i) = *(src_ptr + i); } else { if constexpr (::sus::mem::size_of<T>() > 1u) { constexpr auto max_len = ::sus::num::usize::MAX / ::sus::mem::size_of<T>(); if (dst_len > max_len) { for (::sus::num::usize i; i < dst_len; i += 1u) *(dst_ptr + i) = *(src_ptr + i); return; } } ::sus::ptr::copy_nonoverlapping(::sus::marker::unsafe_fn, src_ptr, dst_ptr, dst_len); } } constexpr void copy_from_slice_unchecked( ::sus::marker::UnsafeFnMarker, const Slice<T>& src) noexcept requires(std::is_trivially_copy_assignable_v<T>) { const ::sus::num::usize dst_len = len(); const T* const src_ptr = src.as_ptr(); T* const dst_ptr = as_mut_ptr(); ::sus::check((src_ptr < dst_ptr && src_ptr <= dst_ptr - dst_len.primitive_value) || (dst_ptr < src_ptr && dst_ptr <= src_ptr - dst_len.primitive_value)); if (std::is_constant_evaluated()) { for (::sus::num::usize i; i < dst_len; i += 1u) *(dst_ptr + i) = *(src_ptr + i); } else { ::sus::ptr::copy_nonoverlapping(::sus::marker::unsafe_fn, src_ptr, dst_ptr, dst_len); } } constexpr void clone_from_slice(const Slice<T>& src) noexcept requires(::sus::mem::Clone<T>) { const ::sus::num::usize src_len = src.len(); const ::sus::num::usize dst_len = len(); ::sus::check(dst_len == src_len); const T* const src_ptr = src.as_ptr(); T* dst_ptr = as_mut_ptr(); for (::sus::num::usize i; i < dst_len; i += 1u) { ::sus::clone_into(*(dst_ptr + i), *(src_ptr + i)); } } constexpr void fill(T value) noexcept requires(::sus::mem::Clone<T>) { T* ptr = as_mut_ptr(); T* const end_ptr = ptr + len(); while (ptr != end_ptr) { ::sus::clone_into(*ptr, value); ptr += 1u; } } constexpr void fill_with(::sus::fn::FnMutRef<T()> f) noexcept { T* ptr = as_mut_ptr(); T* const end_ptr = ptr + len(); while (ptr != end_ptr) { *ptr = ::sus::fn::call_mut(f); ptr += 1u; } } constexpr void fill_with_default() noexcept requires(sus::construct::Default<T>) { T* ptr = as_mut_ptr(); T* const end_ptr = ptr + len(); while (ptr != end_ptr) { *ptr = T(); ptr += 1u; } } __attribute__((pure)) constexpr ::sus::Option<T&> first_mut() & noexcept { if (len() > 0u) return ::sus::Option<T&>::with(*as_mut_ptr()); else return ::sus::Option<T&>(); } __attribute__((pure)) constexpr Option<T&> get_mut(::sus::num::usize i) & noexcept { if (i < len()) [[likely]] return Option<T&>::with(get_unchecked_mut(::sus::marker::unsafe_fn, i)); else return Option<T&>(); } __attribute__((pure)) constexpr inline T& get_unchecked_mut( ::sus::marker::UnsafeFnMarker, ::sus::num::usize i) & noexcept { ::sus::check(i.primitive_value < slice_mut_.slice_.len_.primitive_value); return as_mut_ptr()[size_t{i}]; } __attribute__((pure)) constexpr Option<SliceMut<T>> get_range_mut( const ::sus::ops::RangeBounds<::sus::num::usize> auto range) & noexcept { const ::sus::num::usize length = len(); const ::sus::num::usize rstart = range.start_bound().unwrap_or(0u); const ::sus::num::usize rend = range.end_bound().unwrap_or(length); const ::sus::num::usize rlen = rend >= rstart ? rend - rstart : 0u; if (rlen > length) return sus::none(); if (rstart > length || rstart > length - rlen) return sus::none(); return Option<SliceMut<T>>::with(SliceMut<T>::from_raw_parts_mut( ::sus::marker::unsafe_fn, slice_mut_.slice_.iter_refs_.to_view_from_owner(), as_mut_ptr() + rstart, rlen)); } __attribute__((pure)) constexpr SliceMut<T> get_range_mut_unchecked( ::sus::marker::UnsafeFnMarker, const ::sus::ops::RangeBounds<::sus::num::usize> auto range) & noexcept { const ::sus::num::usize rstart = range.start_bound().unwrap_or(0u); const ::sus::num::usize rend = range.end_bound().unwrap_or(len()); const ::sus::num::usize rlen = rend >= rstart ? rend - rstart : 0u; return SliceMut<T>::from_raw_parts_mut(::sus::marker::unsafe_fn, slice_mut_.slice_.iter_refs_.to_view_from_owner(), as_mut_ptr() + rstart, rlen); } __attribute__((pure)) constexpr SliceIterMut<T&> iter_mut() & noexcept { return SliceIterMut<T&>::with(slice_mut_.slice_.iter_refs_.to_iter_from_owner(), as_mut_ptr(), len()); } __attribute__((pure)) constexpr ::sus::Option<T&> last_mut() & noexcept { const ::sus::num::usize length = len(); if (length > 0u) return ::sus::Option<T&>::with(*(as_mut_ptr() + length - 1u)); else return ::sus::Option<T&>(); } constexpr RChunksExactMut<T> rchunks_exact_mut(::sus::num::usize chunk_size) & noexcept { return RChunksExactMut<T>::with(slice_mut_.slice_.iter_refs_.to_iter_from_owner(), *this, chunk_size); } constexpr RChunksMut<T> rchunks_mut(::sus::num::usize chunk_size) & noexcept { return RChunksMut<T>::with(slice_mut_.slice_.iter_refs_.to_iter_from_owner(), *this, chunk_size); } constexpr void reverse() noexcept requires(::sus::mem::Move<T>) { const auto half_len = len() / 2u; const auto [start, end] = as_mut_ptr_range(); auto front_half = ::sus::containers::SliceMut<T>::from_raw_parts_mut( ::sus::marker::unsafe_fn, slice_mut_.slice_.iter_refs_.to_view_from_owner(), start, half_len); auto back_half = ::sus::containers::SliceMut<T>::from_raw_parts_mut( ::sus::marker::unsafe_fn, slice_mut_.slice_.iter_refs_.to_view_from_owner(), end - half_len, half_len); for (::sus::num::usize i; i < half_len; i += 1u) { ::sus::mem::swap_nonoverlapping(::sus::marker::unsafe_fn, front_half[i], back_half[half_len - 1u - i]); } } void rotate_left(::sus::num::usize mid) noexcept requires(::sus::mem::Move<T>) { const ::sus::num::usize length = len(); ::sus::check(mid <= length); const ::sus::num::usize k = length - mid; T* const p = as_mut_ptr(); if constexpr (::sus::mem::relocate_by_memcpy<T>) { if (!std::is_constant_evaluated()) { } } if (mid == 0u || k == 0u) return; for (::sus::num::usize i; i < k; i += 1u) { ::sus::mem::swap_nonoverlapping(::sus::marker::unsafe_fn, *(p + i), *(p + mid + i)); } if (k < mid) { get_range_mut_unchecked(::sus::marker::unsafe_fn, ::sus::ops::RangeFrom(k)) .rotate_left(mid - k); } else if (k > mid && mid % 2u != (k - mid) % 2u) { if ((k - mid) % 2u == 1u) { for (::sus::num::usize i = k; i < length - 1u; i += 1u) { ::sus::mem::swap_nonoverlapping(::sus::marker::unsafe_fn, *(p + i), *(p + length - 1u)); } } else { for (::sus::num::usize i = k; i < length - 1u; i += 1u) { ::sus::mem::swap_nonoverlapping(::sus::marker::unsafe_fn, *(p + i), *(p + i + 1u)); } } } } void rotate_right(::sus::num::usize k) noexcept requires(::sus::mem::Move<T>) { rotate_left(len() - k); } constexpr RSplitMut<T> rsplit_mut(::sus::fn::FnMutRef<bool(const T&)> pred) & noexcept { return RSplitMut<T>::with( SplitMut<T>::with(slice_mut_.slice_.iter_refs_.to_iter_from_owner(), *this, ::sus::move(pred))); } constexpr RSplitNMut<T> rsplitn_mut( usize n, ::sus::fn::FnMutRef<bool(const T&)> pred) & noexcept { return RSplitNMut<T>::with(RSplitMut<T>::with(SplitMut<T>::with( slice_mut_.slice_.iter_refs_.to_iter_from_owner(), *this, ::sus::move(pred))), n); } void sort() noexcept requires(::sus::ops::Ord<T>) { if (len() > ::sus::num::usize(0u)) { std::stable_sort(as_mut_ptr(), as_mut_ptr() + len()); } } void sort_by(::sus::fn::FnMutRef<std::strong_ordering(const T&, const T&)> compare) noexcept { if (len() > ::sus::num::usize(0u)) { std::stable_sort(as_mut_ptr(), as_mut_ptr() + len(), [&compare](const T& l, const T& r) { return ::sus::fn::call_mut(compare, l, r) < 0; }); } } template <::sus::fn::FnMut<::sus::fn::NonVoid(const T&)> KeyFn, int&..., class Key = std::invoke_result_t<KeyFn&, const T&>> requires(::sus::ops::Ord<Key>) void sort_by_key(KeyFn f) noexcept { return sort_by([&f](const T& a, const T& b) { return ::sus::fn::call_mut(f, a) <=> ::sus::fn::call_mut(f, b); }); } template <::sus::fn::FnMut<::sus::fn::NonVoid(const T&)> KeyFn, int&..., class Key = std::invoke_result_t<KeyFn&, const T&>> requires(::sus::ops::Ord<Key>) void sort_by_cached_key(KeyFn f) noexcept { constexpr auto sz_u8 = ::sus::mem::size_of<::sus::Tuple<Key, u8>>(); constexpr auto sz_u16 = ::sus::mem::size_of<::sus::Tuple<Key, u16>>(); constexpr auto sz_u32 = ::sus::mem::size_of<::sus::Tuple<Key, u32>>(); constexpr auto sz_usize = ::sus::mem::size_of<::sus::Tuple<Key, usize>>(); const auto length = len(); if (length < 2u) { return; } if constexpr (sz_u8 < sz_u16) { if (length <= u8::MAX) { __private::sort_slice_by_cached_key<u8, Key, T>(*this, f); return; } } if constexpr (sz_u16 < sz_u32) { if (length <= u16::MAX) { __private::sort_slice_by_cached_key<u16, Key, T>(*this, f); return; } } if constexpr (sz_u32 < sz_usize) { if (length <= u32::MAX) { __private::sort_slice_by_cached_key<u32, Key, T>(*this, f); return; } } __private::sort_slice_by_cached_key<usize, Key, T>(*this, f); } constexpr void sort_unstable() noexcept requires(::sus::ops::Ord<T>) { if (len() > 0u) { std::sort(as_mut_ptr(), as_mut_ptr() + len()); } } constexpr void sort_unstable_by( ::sus::fn::FnMutRef<std::strong_ordering(const T&, const T&)> compare) noexcept { if (len() > 0u) { std::sort(as_mut_ptr(), as_mut_ptr() + len(), [&compare](const T& l, const T& r) { return ::sus::fn::call_mut(compare, l, r) < 0; }); } } template <::sus::fn::FnMut<::sus::fn::NonVoid(const T&)> KeyFn, int&..., class Key = std::invoke_result_t<KeyFn&, const T&>> requires(::sus::ops::Ord<Key>) void sort_unstable_by_key(KeyFn f) noexcept { return sort_unstable_by([&f](const T& a, const T& b) { return ::sus::fn::call_mut(f, a) <=> ::sus::fn::call_mut(f, b); }); } constexpr SplitMut<T> split_mut(::sus::fn::FnMutRef<bool(const T&)> pred) & noexcept { return SplitMut<T>::with(slice_mut_.slice_.iter_refs_.to_iter_from_owner(), *this, ::sus::move(pred)); } __attribute__((pure)) constexpr ::sus::Tuple<SliceMut<T>, SliceMut<T>> split_at_mut( ::sus::num::usize mid) & noexcept { ::sus::check(mid <= len()); return split_at_mut_unchecked(::sus::marker::unsafe_fn, mid); } __attribute__((pure)) constexpr ::sus::Tuple<SliceMut<T>, SliceMut<T>> split_at_mut_unchecked(::sus::marker::UnsafeFnMarker, ::sus::num::usize mid) & noexcept { ::sus::check(mid.primitive_value <= slice_mut_.slice_.len_.primitive_value); const ::sus::num::usize rem = len().unchecked_sub(::sus::marker::unsafe_fn, mid); return ::sus::Tuple<SliceMut<T>, SliceMut<T>>::with( SliceMut<T>::from_raw_parts_mut(::sus::marker::unsafe_fn, slice_mut_.slice_.iter_refs_.to_view_from_owner(), as_mut_ptr(), mid), SliceMut<T>::from_raw_parts_mut(::sus::marker::unsafe_fn, slice_mut_.slice_.iter_refs_.to_view_from_owner(), as_mut_ptr() + mid, rem)); } __attribute__((pure)) constexpr ::sus::Option<::sus::Tuple<T&, SliceMut<T>>> split_first_mut() & noexcept { if (is_empty()) return ::sus::none(); return ::sus::some( ::sus::tuple(*as_mut_ptr(), get_range_mut_unchecked(::sus::marker::unsafe_fn, ::sus::ops::RangeFrom<usize>(1u)))); } constexpr SplitInclusiveMut<T> split_inclusive_mut( ::sus::fn::FnMutRef<bool(const T&)> pred) & noexcept { return SplitInclusiveMut<T>::with(slice_mut_.slice_.iter_refs_.to_iter_from_owner(), *this, ::sus::move(pred)); } __attribute__((pure)) constexpr ::sus::Option<::sus::Tuple<T&, SliceMut<T>>> split_last_mut() & noexcept { if (is_empty()) return ::sus::none(); const usize last = len() - 1u; return ::sus::some( ::sus::tuple(*(as_mut_ptr() + last), get_range_mut_unchecked(::sus::marker::unsafe_fn, ::sus::ops::RangeTo<usize>(last)))); } constexpr SplitNMut<T> splitn_mut( usize n, ::sus::fn::FnMutRef<bool(const T&)> pred) & noexcept { return SplitNMut<T>::with( SplitMut<T>::with(slice_mut_.slice_.iter_refs_.to_iter_from_owner(), *this, ::sus::move(pred)), n); } constexpr ::sus::Option<SliceMut<T>> strip_prefix_mut(const Slice<T>& prefix) & noexcept requires(::sus::ops::Eq<T>) { const usize n = prefix.len(); if (n <= len()) { auto [head, tail] = split_at_mut(n); if (head == prefix) { return ::sus::Option<SliceMut<T>>::with(tail); } } return ::sus::Option<SliceMut<T>>(); } constexpr ::sus::Option<SliceMut<T>> strip_suffix_mut(const Slice<T>& suffix) & noexcept requires(::sus::ops::Eq<T>) { const auto l = len(); const auto n = suffix.len(); if (n <= l) { auto [head, tail] = split_at_mut(l - n); if (tail == suffix) { return ::sus::Option<SliceMut<T>>::with(head); } } return ::sus::Option<SliceMut<T>>(); } constexpr void swap(usize a, usize b) noexcept { ::sus::check(a < len() && b < len()); ::sus::mem::swap(*(as_mut_ptr() + a), *(as_mut_ptr() + b)); } constexpr void swap_nonoverlapping(::sus::marker::UnsafeFnMarker, usize a, usize b) noexcept { ::sus::check(a.primitive_value != b.primitive_value); ::sus::check(a.primitive_value < slice_mut_.slice_.len_.primitive_value); ::sus::check(b.primitive_value < slice_mut_.slice_.len_.primitive_value); ::sus::mem::swap_nonoverlapping(::sus::marker::unsafe_fn, *(as_mut_ptr() + a), *(as_mut_ptr() + b)); } constexpr void swap_unchecked(::sus::marker::UnsafeFnMarker, usize a, usize b) noexcept { ::sus::check(a.primitive_value < slice_mut_.slice_.len_.primitive_value); ::sus::check(b.primitive_value < slice_mut_.slice_.len_.primitive_value); ::sus::mem::swap(*(as_mut_ptr() + a), *(as_mut_ptr() + b)); } constexpr void swap_with_slice(const SliceMut<T>& other) noexcept { auto const self_len = len(); auto const other_len = other.len(); T* const self_ptr = as_mut_ptr(); T* const other_ptr = other.as_mut_ptr(); ::sus::check(self_len == other_len); if (other_ptr <= self_ptr) { ::sus::check(other_ptr + other_len <= self_ptr); } else { ::sus::check(self_ptr + self_len <= other_ptr); } ::sus::ptr::swap_nonoverlapping(::sus::marker::unsafe_fn, self_ptr, other_ptr, self_len); } __attribute__((pure)) constexpr WindowsMut<T> windows_mut(usize size) & noexcept { ::sus::check(size > 0u); return WindowsMut<T>::with(slice_mut_.slice_.iter_refs_.to_iter_from_owner(), *this, size); } private: constexpr Vec(T* ptr, usize len, usize cap) : slice_mut_(sus::iter::IterRefCounter::for_owner(), ptr, len), capacity_(cap) {} constexpr T* raw_data() const noexcept { return slice_mut_.slice_.data_; } constexpr T*& raw_data() noexcept { return slice_mut_.slice_.data_; } constexpr usize apply_growth_function(usize additional) const noexcept { usize goal = additional + len(); usize cap = capacity_; while (cap < goal) { cap = (cap + 1u) * 3u; auto bytes = ::sus::mem::size_of<T>() * cap; check(bytes <= usize(size_t{(9223372036854775807L)})); } return cap; } constexpr void destroy_storage_objects() { if constexpr (!std::is_trivially_destructible_v<T>) { const auto self_len = len(); for (::sus::num::usize i; i < self_len; i += 1u) (raw_data() + i)->~T(); } } constexpr void free_storage() { destroy_storage_objects(); std::allocator<T>().deallocate(raw_data(), size_t{capacity_}); } constexpr inline bool is_alloced() const noexcept { return capacity_ > 0_usize; } constexpr inline bool is_moved_from() const noexcept { return len() > capacity_; } constexpr inline bool has_iterators() const noexcept { return slice_mut_.slice_.iter_refs_.count_from_owner() != 0u; } static constexpr usize kMovedFromLen = 1_usize; static constexpr usize kMovedFromCapacity = 0_usize; SliceMut<T> slice_mut_; usize capacity_; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<decltype(slice_mut_), decltype(capacity_)>; static_assert(SusUnsafeTrivialRelocate, "Type is not trivially relocatable"); }; template <class T> Vec<T> Vec<T>::to_vec() const& noexcept requires(::sus::mem::Clone<T>) { auto v = Vec<T>::with_capacity(slice_mut_.slice_.len_); for (::sus::usize i; i < slice_mut_.slice_.len_; i += 1u) { v.push(::sus::clone(*(slice_mut_.slice_.data_ + i))); } return v; } using ::sus::iter::__private::begin; using ::sus::iter::__private::end; template <class... Ts> requires(sizeof...(Ts) > 0) [[nodiscard]] inline constexpr auto vec(Ts&&... vs) noexcept { return __private::VecMarker<Ts...>( ::sus::tuple_type::Tuple<Ts&&...>::with(::sus::forward<Ts>(vs)...)); } } template <class T> struct sus::iter::FromIteratorImpl<::sus::containers::Vec<T>> { static constexpr ::sus::containers::Vec<T> from_iter( ::sus::iter::IntoIterator<T> auto&& into_iter) noexcept requires(::sus::mem::Move<T>) { auto&& iter = sus::move(into_iter).into_iter(); auto [lower, upper] = iter.size_hint(); auto v = ::sus::containers::Vec<T>::with_capacity( ::sus::move(upper).unwrap_or(lower)); for (T t : iter) v.push(::sus::move(t)); return v; } }; namespace sus { using ::sus::containers::Vec; using ::sus::containers::vec; } namespace sus::iter { template <class ItemT> class Empty; template <class Item> constexpr inline Empty<Item> empty() noexcept { return Empty<Item>(); } template <class ItemT> class [[nodiscard]] Empty final : public IteratorBase<Empty<ItemT>, ItemT> { public: using Item = ItemT; constexpr Option<Item> next() noexcept { return sus::Option<Item>(); } constexpr SizeHint size_hint() const noexcept { return SizeHint(0u, ::sus::Option<::sus::num::usize>::with(0u)); } constexpr Option<Item> next_back() noexcept { return sus::Option<Item>(); } constexpr usize exact_size_hint() const noexcept { return 0u; } private: friend Empty<Item> sus::iter::empty<Item>() noexcept; constexpr Empty() = default; static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); static_assert(std::is_same_v<decltype(::sus::marker::unsafe_fn), const ::sus::marker::UnsafeFnMarker>); template <class SusOuterClassTypeForTriviallyReloc> friend struct ::sus::mem::__private::relocatable_tag; static constexpr bool SusUnsafeTrivialRelocate = ::sus::mem::relocate_by_memcpy<>; static_assert(SusUnsafeTrivialRelocate, "Type is not trivially relocatable"); }; } namespace sus::iter { inline constexpr auto zip(IntoIteratorAny auto&& iia, IntoIteratorAny auto&& iib) noexcept -> Iterator< ::sus::Tuple<typename IntoIteratorOutputType<decltype(iia)>::Item, typename IntoIteratorOutputType<decltype(iib)>::Item>> auto requires(::sus::mem::IsMoveRef<decltype(iia)> && ::sus::mem::IsMoveRef<decltype(iib)>) { return ::sus::move(iia).into_iter().zip(::sus::move(iib)); } } namespace sus::num { template <::sus::num::Integer I> class OverflowInteger { public: constexpr OverflowInteger() noexcept requires(::sus::construct::Default<I>) : v_(Option<I>::with(I())) {} template <std::convertible_to<I> U> __attribute__((pure)) static constexpr OverflowInteger with(U u) noexcept { return OverflowInteger(CONSTRUCT, u); } template <class U> requires(::sus::construct::From<I, U>) __attribute__((pure)) static constexpr OverflowInteger from(U u) noexcept { return OverflowInteger(CONSTRUCT, ::sus::move_into(u)); } template <class U> requires(::sus::construct::TryFrom<I, U>) __attribute__((pure)) static constexpr ::sus::result::Result<OverflowInteger, ::sus::num::TryFromIntError> try_from(U u) noexcept { if (auto r = I::try_from(u); r.is_ok()) { return ::sus::result::ok( OverflowInteger(CONSTRUCT, ::sus::move(r).unwrap())); } else { return ::sus::result::err(::sus::move(r).unwrap_err()); } } static constexpr OverflowInteger from_product( ::sus::iter::Iterator<I> auto&& it) noexcept { auto p = OverflowInteger( CONSTRUCT, ::sus::mog<I>(1)); for (I i : ::sus::move(it)) p *= i; return p; } static constexpr OverflowInteger from_product( ::sus::iter::Iterator<OverflowInteger> auto&& it) noexcept { auto p = OverflowInteger( CONSTRUCT, ::sus::mog<I>(1)); for (OverflowInteger i : ::sus::move(it)) p *= i; return p; } __attribute__((pure)) bool is_valid() const noexcept { return v_.is_some(); } __attribute__((pure)) bool is_overflow() const noexcept { return v_.is_none(); } __attribute__((pure)) constexpr I as_value() const& noexcept { return v_.as_value(); } __attribute__((pure)) constexpr I as_value_unchecked( ::sus::marker::UnsafeFnMarker) const& noexcept { return v_.as_value_unchecked(::sus::marker::unsafe_fn); } __attribute__((pure)) constexpr I& as_value_mut() & noexcept { return v_.as_value_mut(); } __attribute__((pure)) constexpr I& as_value_unchecked_mut( ::sus::marker::UnsafeFnMarker) & noexcept { return v_.as_value_unchecked_mut(::sus::marker::unsafe_fn); } constexpr I unwrap() && noexcept { return ::sus::move(v_).unwrap(); } constexpr I unwrap_unchecked(::sus::marker::UnsafeFnMarker) && noexcept { return ::sus::move(v_).unwrap_unchecked(::sus::marker::unsafe_fn); } __attribute__((pure)) constexpr Option<I> to_option() const noexcept { return v_; } constexpr void operator+=(I rhs) noexcept { v_ = v_.and_then([=](I vi) { return vi.checked_add(rhs); }); } constexpr void operator-=(I rhs) noexcept { v_ = v_.and_then([=](I vi) { return vi.checked_sub(rhs); }); } constexpr void operator*=(I rhs) noexcept { v_ = v_.and_then([=](I vi) { return vi.checked_mul(rhs); }); } constexpr void operator/=(I rhs) noexcept { v_ = v_.and_then([=](I vi) { return vi.checked_div(rhs); }); } constexpr void operator%=(I rhs) noexcept { v_ = v_.and_then([=](I vi) { return vi.checked_rem(rhs); }); } constexpr void operator+=(OverflowInteger rhs) noexcept { v_ = v_.and_then([=](I vi) { return rhs.v_.and_then([=](I rhsi) { return vi.checked_add(rhsi); }); }); } constexpr void operator-=(OverflowInteger rhs) noexcept { v_ = v_.and_then([=](I vi) { return rhs.v_.and_then([=](I rhsi) { return vi.checked_sub(rhsi); }); }); } constexpr void operator*=(OverflowInteger rhs) noexcept { v_ = v_.and_then([=](I vi) { return rhs.v_.and_then([=](I rhsi) { return vi.checked_mul(rhsi); }); }); } constexpr void operator/=(OverflowInteger rhs) noexcept { v_ = v_.and_then([=](I vi) { return rhs.v_.and_then([=](I rhsi) { return vi.checked_div(rhsi); }); }); } constexpr void operator%=(OverflowInteger rhs) noexcept { v_ = v_.and_then([=](I vi) { return rhs.v_.and_then([=](I rhsi) { return vi.checked_rem(rhsi); }); }); } __attribute__((pure)) friend constexpr OverflowInteger operator+(OverflowInteger lhs, I rhs) noexcept { return OverflowInteger(FROM_OPTION, lhs.v_.and_then([=](I lhsi) { return lhsi.checked_add(rhs); })); } __attribute__((pure)) friend constexpr OverflowInteger operator-(OverflowInteger lhs, I rhs) noexcept { return OverflowInteger(FROM_OPTION, lhs.v_.and_then([=](I lhsi) { return lhsi.checked_sub(rhs); })); } __attribute__((pure)) friend constexpr OverflowInteger operator*(OverflowInteger lhs, I rhs) noexcept { return OverflowInteger(FROM_OPTION, lhs.v_.and_then([=](I lhsi) { return lhsi.checked_mul(rhs); })); } __attribute__((pure)) friend constexpr OverflowInteger operator/(OverflowInteger lhs, I rhs) noexcept { return OverflowInteger(FROM_OPTION, lhs.v_.and_then([=](I lhsi) { return lhsi.checked_div(rhs); })); } __attribute__((pure)) friend constexpr OverflowInteger operator%(OverflowInteger lhs, I rhs) noexcept { return OverflowInteger(FROM_OPTION, lhs.v_.and_then([=](I lhsi) { return lhsi.checked_rem(rhs); })); } __attribute__((pure)) friend constexpr OverflowInteger operator+( I lhs, OverflowInteger rhs) noexcept { return OverflowInteger(FROM_OPTION, rhs.v_.and_then([=](I rhsi) { return lhs.checked_add(rhsi); })); } __attribute__((pure)) friend constexpr OverflowInteger operator-( I lhs, OverflowInteger rhs) noexcept { return OverflowInteger(FROM_OPTION, rhs.v_.and_then([=](I rhsi) { return lhs.checked_sub(rhsi); })); } __attribute__((pure)) friend constexpr OverflowInteger operator*( I lhs, OverflowInteger rhs) noexcept { return OverflowInteger(FROM_OPTION, rhs.v_.and_then([=](I rhsi) { return lhs.checked_mul(rhsi); })); } __attribute__((pure)) friend constexpr OverflowInteger operator/( I lhs, OverflowInteger rhs) noexcept { return OverflowInteger(FROM_OPTION, rhs.v_.and_then([=](I rhsi) { return lhs.checked_div(rhsi); })); } __attribute__((pure)) friend constexpr OverflowInteger operator%( I lhs, OverflowInteger rhs) noexcept { return OverflowInteger(FROM_OPTION, rhs.v_.and_then([=](I rhsi) { return lhs.checked_rem(rhsi); })); } __attribute__((pure)) friend constexpr OverflowInteger operator+( OverflowInteger lhs, OverflowInteger rhs) noexcept { return OverflowInteger(FROM_OPTION, lhs.v_.and_then([=](I lhsi) { return rhs.v_.and_then([=](I rhsi) { return lhsi.checked_add(rhsi); }); })); } __attribute__((pure)) friend constexpr OverflowInteger operator-( OverflowInteger lhs, OverflowInteger rhs) noexcept { return OverflowInteger(FROM_OPTION, lhs.v_.and_then([=](I lhsi) { return rhs.v_.and_then([=](I rhsi) { return lhsi.checked_sub(rhsi); }); })); } __attribute__((pure)) friend constexpr OverflowInteger operator*( OverflowInteger lhs, OverflowInteger rhs) noexcept { return OverflowInteger(FROM_OPTION, lhs.v_.and_then([=](I lhsi) { return rhs.v_.and_then([=](I rhsi) { return lhsi.checked_mul(rhsi); }); })); } __attribute__((pure)) friend constexpr OverflowInteger operator/( OverflowInteger lhs, OverflowInteger rhs) noexcept { return OverflowInteger(FROM_OPTION, lhs.v_.and_then([=](I lhsi) { return rhs.v_.and_then([=](I rhsi) { return lhsi.checked_div(rhsi); }); })); } __attribute__((pure)) friend constexpr OverflowInteger operator%( OverflowInteger lhs, OverflowInteger rhs) noexcept { return OverflowInteger(FROM_OPTION, lhs.v_.and_then([=](I lhsi) { return rhs.v_.and_then([=](I rhsi) { return lhsi.checked_rem(rhsi); }); })); } friend bool operator==(OverflowInteger lhs, OverflowInteger rhs) noexcept { return lhs.v_ == rhs.v_; } friend bool operator==(OverflowInteger lhs, I rhs) noexcept { return lhs.is_valid() && lhs.v_.as_value_unchecked(::sus::marker::unsafe_fn) == rhs; } friend bool operator==(I lhs, OverflowInteger rhs) noexcept { return rhs.is_valid() && lhs == rhs.v_.as_value_unchecked(::sus::marker::unsafe_fn); } friend auto operator<=>(OverflowInteger lhs, OverflowInteger rhs) noexcept { if (lhs.is_overflow()) { if (rhs.is_overflow()) { return std::strong_ordering::equivalent; } else { return std::strong_ordering::greater; } } else if (rhs.is_overflow()) { return std::strong_ordering::less; } else { return lhs.v_.as_value_unchecked(::sus::marker::unsafe_fn) <=> rhs.v_.as_value_unchecked(::sus::marker::unsafe_fn); } } friend auto operator<=>(OverflowInteger lhs, I rhs) noexcept { if (lhs.is_overflow()) { return std::strong_ordering::greater; } else { return lhs.v_.as_value_unchecked(::sus::marker::unsafe_fn) <=> rhs; } } friend auto operator<=>(I lhs, OverflowInteger rhs) noexcept { if (rhs.is_overflow()) { return std::strong_ordering::less; } else { return lhs <=> rhs.v_.as_value_unchecked(::sus::marker::unsafe_fn); } } private: enum Construct { CONSTRUCT }; explicit inline constexpr OverflowInteger(Construct, I i) noexcept : v_(Option<I>::with(i)) {} enum FromOption { FROM_OPTION }; explicit inline constexpr OverflowInteger(FromOption, Option<I> o) noexcept : v_(::sus::move(o)) {} Option<I> v_; }; } namespace sus::num::__private { template <class T> requires(std::is_floating_point_v<T> && ::sus::mem::size_of<T>() <= 8) __attribute__((const)) inline constexpr std::strong_ordering float_strong_ordering(T l, T r) noexcept { if (into_unsigned_integer(l) == into_unsigned_integer(r)) return std::strong_ordering::equal; const bool l_neg = (into_unsigned_integer(l) & high_bit<T>()) != 0; const bool r_neg = (into_unsigned_integer(r) & high_bit<T>()) != 0; if (l_neg != r_neg) { if (l_neg) return std::strong_ordering::less; else return std::strong_ordering::greater; } const bool l_nan = float_is_nan(l); const bool r_nan = float_is_nan(r); if (l_nan != r_nan) { if (l_neg == l_nan) return std::strong_ordering::less; else return std::strong_ordering::greater; } if (l_nan && r_nan) { const bool l_quiet = float_is_nan_quiet(l); const bool r_quiet = float_is_nan_quiet(r); if (l_quiet != r_quiet) { if (l_neg == float_is_nan_quiet(l)) return std::strong_ordering::less; else return std::strong_ordering::greater; } else { if (l_neg) { return std::strong_order(into_unsigned_integer(r), into_unsigned_integer(l)); } else { return std::strong_order(into_unsigned_integer(l), into_unsigned_integer(r)); } } } if (l < r) return std::strong_ordering::less; else return std::strong_ordering::greater; } } namespace sus::num { struct f32 final { float primitive_value = float{0.0}; static const float MIN_PRIMITIVE; static const float MAX_PRIMITIVE; static const f32 MIN; static const f32 MAX; static const u32 RADIX; static const u32 MANTISSA_DIGITS; static const u32 DIGITS; static const f32 EPSILON; static const f32 MIN_POSITIVE; static const i32 MIN_EXP; static const i32 MAX_EXP; static const i32 MIN_10_EXP; static const i32 MAX_10_EXP; static const f32 NAN; static const f32 INFINITY; static const f32 NEG_INFINITY; struct consts { static const f32 E; static const f32 FRAC_1_PI; static const f32 FRAC_1_SQRT_2; static const f32 FRAC_2_PI; static const f32 FRAC_2_SQRT_PI; static const f32 FRAC_PI_2; static const f32 FRAC_PI_3; static const f32 FRAC_PI_4; static const f32 FRAC_PI_6; static const f32 FRAC_PI_8; static const f32 LN_2; static const f32 LN_10; static const f32 LOG2_10; static const f32 LOG2_E; static const f32 LOG10_2; static const f32 LOG10_E; static const f32 PI; static const f32 SQRT_2; static const f32 TAU; }; constexpr inline f32() noexcept = default; template <Float F> requires(::sus::mem::size_of<F>() <= ::sus::mem::size_of<float>()) constexpr inline f32(F v) noexcept : primitive_value(v.primitive_value) {} template <PrimitiveFloat P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of<float>()) constexpr inline f32(P v) noexcept : primitive_value(v) {} template <Float F> requires(::sus::mem::size_of<F>() <= ::sus::mem::size_of<float>()) __attribute__((pure)) static constexpr f32 from(F f) noexcept { return f32(f); } template <PrimitiveFloat F> requires(::sus::mem::size_of<F>() <= ::sus::mem::size_of<float>()) __attribute__((pure)) static constexpr f32 from(F f) noexcept { return f32(f); } template <Float F> requires(::sus::mem::size_of<F>() <= ::sus::mem::size_of<float>()) constexpr inline f32& operator=(F v) noexcept { primitive_value = v.primitive_value; return *this; } template <PrimitiveFloat P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of<float>()) constexpr inline f32& operator=(P v) noexcept { primitive_value = v; return *this; } static constexpr f32 from_sum( ::sus::iter::Iterator<f32> auto&& it) noexcept { auto p = f32(float{0u}); for (f32 i : ::sus::move(it)) p += i; return p; } static constexpr f32 from_product( ::sus::iter::Iterator<f32> auto&& it) noexcept { auto p = f32(float{1u}); for (f32 i : ::sus::move(it)) p *= i; return p; } template <PrimitiveFloat U> requires(::sus::mem::size_of<U>() >= ::sus::mem::size_of<float>()) __attribute__((pure)) constexpr inline explicit operator U() const { return primitive_value; } template <PrimitiveFloat F> [[nodiscard]] __attribute__((pure)) friend constexpr inline bool operator==( f32 l, f32 r) noexcept { return (l.primitive_value <=> r.primitive_value) == 0; } template <PrimitiveFloat F> [[nodiscard]] __attribute__((pure)) friend constexpr inline bool operator==(f32 l, F r) noexcept { return (l.primitive_value <=> r) == 0; } template <Float F> [[nodiscard]] __attribute__((pure)) friend constexpr inline bool operator==(f32 l, F r) noexcept { return (l.primitive_value <=> r.primitive_value) == 0; } template <PrimitiveFloat F> [[nodiscard]] __attribute__((pure)) friend constexpr inline auto operator<=>( f32 l, f32 r) noexcept { return l.primitive_value <=> r.primitive_value; } template <PrimitiveFloat F> [[nodiscard]] __attribute__((pure)) friend constexpr inline auto operator<=>(f32 l, F r) noexcept { return l.primitive_value <=> r; } template <Float F> [[nodiscard]] __attribute__((pure)) friend constexpr inline auto operator<=>(f32 l, F r) noexcept { return l.primitive_value <=> r.primitive_value; } __attribute__((pure)) constexpr std::strong_ordering total_cmp(f32 other) const& noexcept { return __private::float_strong_ordering(primitive_value, other.primitive_value); } __attribute__((pure)) constexpr inline f32 operator-() const { return f32(-primitive_value); } [[nodiscard]] __attribute__((pure)) friend constexpr inline f32 operator+( f32 l, f32 r) noexcept { return l.primitive_value + r.primitive_value; } [[nodiscard]] __attribute__((pure)) friend constexpr inline f32 operator-( f32 l, f32 r) noexcept { return l.primitive_value - r.primitive_value; } [[nodiscard]] __attribute__((pure)) friend constexpr inline f32 operator*( f32 l, f32 r) noexcept { return l.primitive_value * r.primitive_value; } [[nodiscard]] __attribute__((pure)) friend constexpr inline f32 operator/( f32 l, f32 r) noexcept { return l.primitive_value / r.primitive_value; } [[nodiscard]] __attribute__((pure)) friend constexpr inline f32 operator%( f32 l, f32 r) noexcept { const auto x = l.primitive_value; const auto y = r.primitive_value; return x - __private::truncate_float(x / y) * y; } constexpr inline void operator+=(f32 r) & noexcept { primitive_value += r.primitive_value; } constexpr inline void operator-=(f32 r) & noexcept { primitive_value -= r.primitive_value; } constexpr inline void operator*=(f32 r) & noexcept { primitive_value *= r.primitive_value; } constexpr inline void operator/=(f32 r) & noexcept { primitive_value /= r.primitive_value; } constexpr inline void operator%=(f32 r) & noexcept { const auto x = primitive_value; const auto y = r.primitive_value; primitive_value = x - __private::truncate_float(x / y) * y; } __attribute__((pure)) inline f32 abs() const& noexcept { return __private::into_float( __private::into_unsigned_integer(primitive_value) & ~__private::high_bit<float>()); } __attribute__((pure)) inline f32 acos() const& noexcept { if (primitive_value < float{-1} || primitive_value > float{1}) [[unlikely]] return NAN; return static_cast<float>(::acos(primitive_value)); } __attribute__((pure)) inline f32 acosh() const& noexcept { if (primitive_value < float{-1}) [[unlikely]] return NAN; return static_cast<float>(::acosh(primitive_value)); } __attribute__((pure)) inline f32 asin() const& noexcept { if (primitive_value < float{-1} || primitive_value > float{1}) [[unlikely]] return NAN; return static_cast<float>(::asin(primitive_value)); } __attribute__((pure)) inline f32 asinh() const& noexcept { if (primitive_value < float{-1}) [[unlikely]] return NAN; return static_cast<float>(::asinh(primitive_value)); } __attribute__((pure)) inline f32 atan() const& noexcept { return static_cast<float>(::atan(primitive_value)); } __attribute__((pure)) inline f32 atan2(f32 other) const& noexcept { return static_cast<float>( ::atan2(primitive_value, other.primitive_value)); } __attribute__((pure)) inline f32 atanh() const& noexcept { return static_cast<float>(::atanh(primitive_value)); } __attribute__((pure)) inline f32 cbrt() const& noexcept { return static_cast<float>(::cbrt(primitive_value)); } __attribute__((pure)) inline f32 ceil() const& noexcept { return static_cast<float>(::ceil(primitive_value)); } __attribute__((pure)) inline f32 copysign(f32 sign) const& noexcept { return static_cast<float>( ::copysign(primitive_value, sign.primitive_value)); } __attribute__((pure)) inline f32 cos() const& noexcept { return static_cast<float>(::cos(primitive_value)); } __attribute__((pure)) inline f32 cosh() const& noexcept { return static_cast<float>(::cosh(primitive_value)); } __attribute__((pure)) inline f32 exp() const& noexcept { return static_cast<float>(::exp(primitive_value)); } __attribute__((pure)) inline f32 exp2() const& noexcept { return static_cast<float>(::exp2(primitive_value)); } __attribute__((pure)) inline f32 exp_m1() const& noexcept { return static_cast<float>(::expm1(primitive_value)); } __attribute__((pure)) inline f32 floor() const& noexcept { return static_cast<float>(::floor(primitive_value)); } __attribute__((pure)) inline f32 hypot(f32 other) const& noexcept { return static_cast<float>( ::hypot(primitive_value, other.primitive_value)); } __attribute__((pure)) inline f32 ln() const& noexcept { return static_cast<float>(::log(primitive_value)); } __attribute__((pure)) inline f32 ln_1p() const& noexcept { return static_cast<float>(::log1p(primitive_value)); } __attribute__((pure)) inline f32 log10() const& noexcept { return static_cast<float>(::log10(primitive_value)); } __attribute__((pure)) inline f32 log2() const& noexcept { return static_cast<float>(::log2(primitive_value)); } __attribute__((pure)) inline f32 log(f32 base) const& noexcept { return ln() / base.ln(); } __attribute__((pure)) inline f32 max(f32 other) const& noexcept { return static_cast<float>( ::fmax(primitive_value, other.primitive_value)); } __attribute__((pure)) inline f32 min(f32 other) const& noexcept { return static_cast<float>( ::fmin(primitive_value, other.primitive_value)); } __attribute__((pure)) inline f32 mul_add(f32 a, f32 b) const& noexcept { return static_cast<float>( ::fma(primitive_value, a.primitive_value, b.primitive_value)); } __attribute__((pure)) inline f32 next_toward(f32 toward) const& noexcept { return __private::next_toward(primitive_value, toward.primitive_value); } __attribute__((pure)) inline f32 powf(f32 n) const& noexcept { return static_cast<float>(::pow(primitive_value, n.primitive_value)); } __attribute__((pure)) inline f32 powi(i32 n) const& noexcept { return static_cast<float>( ::pow(primitive_value, int{n.primitive_value})); } __attribute__((pure)) inline f32 recip() const& noexcept { return float{1} / primitive_value; } __attribute__((pure)) inline f32 round() const& noexcept { return __private::float_round(primitive_value); } __attribute__((pure)) inline f32 signum() const& noexcept { return __private::float_signum(primitive_value); } __attribute__((pure)) inline f32 sin() const& noexcept { return static_cast<float>(::sin(primitive_value)); } __attribute__((pure)) inline f32 sinh() const& noexcept { return static_cast<float>(::sinh(primitive_value)); } __attribute__((pure)) inline f32 sqrt() const& noexcept { if (primitive_value < -float{0}) [[unlikely]] return NAN; return static_cast<float>(::sqrt(primitive_value)); } __attribute__((pure)) inline f32 tan() const& noexcept { return static_cast<float>(::tan(primitive_value)); } __attribute__((pure)) inline f32 tanh() const& noexcept { return static_cast<float>(::tanh(primitive_value)); } __attribute__((pure)) inline f32 fract() const& noexcept { return primitive_value - __private::truncate_float(primitive_value); } __attribute__((pure)) inline f32 trunc() const& noexcept { return __private::truncate_float(primitive_value); } __attribute__((pure)) inline f32 to_degrees() const& noexcept { constexpr auto PIS_IN_180 = float{57.2957795130823208767981548141051703}; return primitive_value * PIS_IN_180; } __attribute__((pure)) inline f32 to_radians() const& noexcept { return primitive_value * (consts::PI.primitive_value / float{180}); } template <Integer I> __attribute__((pure)) constexpr inline I to_int_unchecked( ::sus::marker::UnsafeFnMarker) const& noexcept { return static_cast<decltype(I::primitive_value)>(primitive_value); } __attribute__((pure)) static f32 from_bits(u32 v) noexcept { return std::bit_cast<f32>(v); } __attribute__((pure)) constexpr inline u32 to_bits() const& noexcept { return std::bit_cast<decltype(u32::primitive_value)>(primitive_value); } __attribute__((pure)) constexpr inline FpCategory classify() const& noexcept { return __private::float_category(primitive_value); } __attribute__((pure)) constexpr inline bool is_finite() const& noexcept { return !__private::float_is_inf_or_nan(primitive_value); } __attribute__((pure)) constexpr inline bool is_infinite() const& noexcept { return __private::float_is_inf(primitive_value); } __attribute__((pure)) constexpr inline bool is_nan() const& noexcept { return __private::float_is_nan(primitive_value); } __attribute__((pure)) constexpr inline bool is_normal() const& noexcept { return __private::float_is_normal(primitive_value); } __attribute__((pure)) constexpr inline bool is_sign_negative() const& noexcept { return __private::float_signbit(primitive_value); } __attribute__((pure)) constexpr inline bool is_sign_positive() const& noexcept { return !__private::float_signbit(primitive_value); } __attribute__((pure)) constexpr inline bool is_subnormal() const& noexcept { return !__private::float_is_zero(primitive_value) && __private::float_nonzero_is_subnormal(primitive_value); } __attribute__((pure)) constexpr inline f32 clamp(f32 min, f32 max) const& noexcept { check(!min.is_nan() && !max.is_nan() && min.primitive_value <= max.primitive_value); return __private::float_clamp(::sus::marker::unsafe_fn, primitive_value, min.primitive_value, max.primitive_value); } __attribute__((pure)) f32 div_euclid(f32 rhs) const& noexcept { const auto q = (*this / rhs).trunc(); if (*this % rhs < float{0}) { if (rhs > f32{float{0}}) return q - f32{float{1}}; else return q + f32{float{1}}; } return q; } __attribute__((pure)) f32 rem_euclid(f32 rhs) const& noexcept { const auto r = *this % rhs; if (r < f32{float{0}}) return r + rhs.abs(); else return r; } __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<float>()> to_be_bytes() const& noexcept; __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<float>()> to_le_bytes() const& noexcept; __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<float>()> to_ne_bytes() const& noexcept; __attribute__((pure)) static f32 from_be_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<float>()>& bytes) noexcept; __attribute__((pure)) static f32 from_le_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<float>()>& bytes) noexcept; __attribute__((pure)) static f32 from_ne_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<float>()>& bytes) noexcept; }; inline constexpr float f32::MIN_PRIMITIVE = __private::min_value<float>(); inline constexpr float f32::MAX_PRIMITIVE = __private::max_value<float>(); inline constexpr f32 f32::MIN = f32(f32::MIN_PRIMITIVE); inline constexpr f32 f32::MAX = f32(f32::MAX_PRIMITIVE); inline constexpr u32 f32::RADIX = __private::radix<float>(); inline constexpr u32 f32::MANTISSA_DIGITS = __private::num_mantissa_digits<float>(); inline constexpr u32 f32::DIGITS = __private::num_digits<float>(); inline constexpr f32 f32::EPSILON = f32(__private::epsilon<float>()); inline constexpr f32 f32::MIN_POSITIVE = f32(__private::min_positive_value<float>()); inline constexpr i32 f32::MIN_EXP = __private::min_exp<float>(); inline constexpr i32 f32::MAX_EXP = __private::max_exp<float>(); inline constexpr i32 f32::MIN_10_EXP = __private::min_10_exp<float>(); inline constexpr i32 f32::MAX_10_EXP = __private::max_10_exp<float>(); inline constexpr f32 f32::NAN = f32(__private::nan<float>()); inline constexpr f32 f32::INFINITY = f32(__private::infinity<float>()); inline constexpr f32 f32::NEG_INFINITY = f32(__private::negative_infinity<float>()); inline constexpr f32 f32::consts::E = f32(2.718281828459045235360287471352662f); inline constexpr f32 f32::consts::FRAC_1_PI = f32(0.318309886183790671537767526745028f); inline constexpr f32 f32::consts::FRAC_1_SQRT_2 = f32(0.7071067811865476f); inline constexpr f32 f32::consts::FRAC_2_PI = f32(0.6366197723675814f); inline constexpr f32 f32::consts::FRAC_2_SQRT_PI = f32(1.1283791670955126f); inline constexpr f32 f32::consts::FRAC_PI_2 = f32(1.5707963267948966f); inline constexpr f32 f32::consts::FRAC_PI_3 = f32(1.0471975511965979f); inline constexpr f32 f32::consts::FRAC_PI_4 = f32(0.7853981633974483f); inline constexpr f32 f32::consts::FRAC_PI_6 = f32(0.5235987755982989f); inline constexpr f32 f32::consts::FRAC_PI_8 = f32(0.39269908169872414f); inline constexpr f32 f32::consts::LN_2 = f32(0.693147180559945309417232121458176f); inline constexpr f32 f32::consts::LN_10 = f32(2.302585092994045684017991454684364f); inline constexpr f32 f32::consts::LOG2_10 = f32(3.321928094887362f); inline constexpr f32 f32::consts::LOG2_E = f32(1.4426950408889634f); inline constexpr f32 f32::consts::LOG10_2 = f32(0.3010299956639812f); inline constexpr f32 f32::consts::LOG10_E = f32(0.4342944819032518f); inline constexpr f32 f32::consts::PI = f32(3.141592653589793238462643383279502f); inline constexpr f32 f32::consts::SQRT_2 = f32(1.414213562373095048801688724209698f); inline constexpr f32 f32::consts::TAU = f32(6.283185307179586f); struct f64 final { double primitive_value = double{0.0}; static const double MIN_PRIMITIVE; static const double MAX_PRIMITIVE; static const f64 MIN; static const f64 MAX; static const u32 RADIX; static const u32 MANTISSA_DIGITS; static const u32 DIGITS; static const f64 EPSILON; static const f64 MIN_POSITIVE; static const i32 MIN_EXP; static const i32 MAX_EXP; static const i32 MIN_10_EXP; static const i32 MAX_10_EXP; static const f64 NAN; static const f64 INFINITY; static const f64 NEG_INFINITY; struct consts { static const f64 E; static const f64 FRAC_1_PI; static const f64 FRAC_1_SQRT_2; static const f64 FRAC_2_PI; static const f64 FRAC_2_SQRT_PI; static const f64 FRAC_PI_2; static const f64 FRAC_PI_3; static const f64 FRAC_PI_4; static const f64 FRAC_PI_6; static const f64 FRAC_PI_8; static const f64 LN_2; static const f64 LN_10; static const f64 LOG2_10; static const f64 LOG2_E; static const f64 LOG10_2; static const f64 LOG10_E; static const f64 PI; static const f64 SQRT_2; static const f64 TAU; }; constexpr inline f64() noexcept = default; template <Float F> requires(::sus::mem::size_of<F>() <= ::sus::mem::size_of<double>()) constexpr inline f64(F v) noexcept : primitive_value(v.primitive_value) {} template <PrimitiveFloat P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of<double>()) constexpr inline f64(P v) noexcept : primitive_value(v) {} template <Float F> requires(::sus::mem::size_of<F>() <= ::sus::mem::size_of<double>()) __attribute__((pure)) static constexpr f64 from(F f) noexcept { return f64(f); } template <PrimitiveFloat F> requires(::sus::mem::size_of<F>() <= ::sus::mem::size_of<double>()) __attribute__((pure)) static constexpr f64 from(F f) noexcept { return f64(f); } template <Float F> requires(::sus::mem::size_of<F>() <= ::sus::mem::size_of<double>()) constexpr inline f64& operator=(F v) noexcept { primitive_value = v.primitive_value; return *this; } template <PrimitiveFloat P> requires(::sus::mem::size_of<P>() <= ::sus::mem::size_of<double>()) constexpr inline f64& operator=(P v) noexcept { primitive_value = v; return *this; } static constexpr f64 from_sum( ::sus::iter::Iterator<f64> auto&& it) noexcept { auto p = f64(double{0u}); for (f64 i : ::sus::move(it)) p += i; return p; } static constexpr f64 from_product( ::sus::iter::Iterator<f64> auto&& it) noexcept { auto p = f64(double{1u}); for (f64 i : ::sus::move(it)) p *= i; return p; } template <PrimitiveFloat U> requires(::sus::mem::size_of<U>() >= ::sus::mem::size_of<double>()) __attribute__((pure)) constexpr inline explicit operator U() const { return primitive_value; } template <PrimitiveFloat F> [[nodiscard]] __attribute__((pure)) friend constexpr inline bool operator==( f64 l, f64 r) noexcept { return (l.primitive_value <=> r.primitive_value) == 0; } template <PrimitiveFloat F> [[nodiscard]] __attribute__((pure)) friend constexpr inline bool operator==(f64 l, F r) noexcept { return (l.primitive_value <=> r) == 0; } template <Float F> [[nodiscard]] __attribute__((pure)) friend constexpr inline bool operator==(f64 l, F r) noexcept { return (l.primitive_value <=> r.primitive_value) == 0; } template <PrimitiveFloat F> [[nodiscard]] __attribute__((pure)) friend constexpr inline auto operator<=>( f64 l, f64 r) noexcept { return l.primitive_value <=> r.primitive_value; } template <PrimitiveFloat F> [[nodiscard]] __attribute__((pure)) friend constexpr inline auto operator<=>(f64 l, F r) noexcept { return l.primitive_value <=> r; } template <Float F> [[nodiscard]] __attribute__((pure)) friend constexpr inline auto operator<=>(f64 l, F r) noexcept { return l.primitive_value <=> r.primitive_value; } __attribute__((pure)) constexpr std::strong_ordering total_cmp(f64 other) const& noexcept { return __private::float_strong_ordering(primitive_value, other.primitive_value); } __attribute__((pure)) constexpr inline f64 operator-() const { return f64(-primitive_value); } [[nodiscard]] __attribute__((pure)) friend constexpr inline f64 operator+( f64 l, f64 r) noexcept { return l.primitive_value + r.primitive_value; } [[nodiscard]] __attribute__((pure)) friend constexpr inline f64 operator-( f64 l, f64 r) noexcept { return l.primitive_value - r.primitive_value; } [[nodiscard]] __attribute__((pure)) friend constexpr inline f64 operator*( f64 l, f64 r) noexcept { return l.primitive_value * r.primitive_value; } [[nodiscard]] __attribute__((pure)) friend constexpr inline f64 operator/( f64 l, f64 r) noexcept { return l.primitive_value / r.primitive_value; } [[nodiscard]] __attribute__((pure)) friend constexpr inline f64 operator%( f64 l, f64 r) noexcept { const auto x = l.primitive_value; const auto y = r.primitive_value; return x - __private::truncate_float(x / y) * y; } constexpr inline void operator+=(f64 r) & noexcept { primitive_value += r.primitive_value; } constexpr inline void operator-=(f64 r) & noexcept { primitive_value -= r.primitive_value; } constexpr inline void operator*=(f64 r) & noexcept { primitive_value *= r.primitive_value; } constexpr inline void operator/=(f64 r) & noexcept { primitive_value /= r.primitive_value; } constexpr inline void operator%=(f64 r) & noexcept { const auto x = primitive_value; const auto y = r.primitive_value; primitive_value = x - __private::truncate_float(x / y) * y; } __attribute__((pure)) inline f64 abs() const& noexcept { return __private::into_float( __private::into_unsigned_integer(primitive_value) & ~__private::high_bit<double>()); } __attribute__((pure)) inline f64 acos() const& noexcept { if (primitive_value < double{-1} || primitive_value > double{1}) [[unlikely]] return NAN; return static_cast<double>(::acos(primitive_value)); } __attribute__((pure)) inline f64 acosh() const& noexcept { if (primitive_value < double{-1}) [[unlikely]] return NAN; return static_cast<double>(::acosh(primitive_value)); } __attribute__((pure)) inline f64 asin() const& noexcept { if (primitive_value < double{-1} || primitive_value > double{1}) [[unlikely]] return NAN; return static_cast<double>(::asin(primitive_value)); } __attribute__((pure)) inline f64 asinh() const& noexcept { if (primitive_value < double{-1}) [[unlikely]] return NAN; return static_cast<double>(::asinh(primitive_value)); } __attribute__((pure)) inline f64 atan() const& noexcept { return static_cast<double>(::atan(primitive_value)); } __attribute__((pure)) inline f64 atan2(f64 other) const& noexcept { return static_cast<double>( ::atan2(primitive_value, other.primitive_value)); } __attribute__((pure)) inline f64 atanh() const& noexcept { return static_cast<double>(::atanh(primitive_value)); } __attribute__((pure)) inline f64 cbrt() const& noexcept { return static_cast<double>(::cbrt(primitive_value)); } __attribute__((pure)) inline f64 ceil() const& noexcept { return static_cast<double>(::ceil(primitive_value)); } __attribute__((pure)) inline f64 copysign(f64 sign) const& noexcept { return static_cast<double>( ::copysign(primitive_value, sign.primitive_value)); } __attribute__((pure)) inline f64 cos() const& noexcept { return static_cast<double>(::cos(primitive_value)); } __attribute__((pure)) inline f64 cosh() const& noexcept { return static_cast<double>(::cosh(primitive_value)); } __attribute__((pure)) inline f64 exp() const& noexcept { return static_cast<double>(::exp(primitive_value)); } __attribute__((pure)) inline f64 exp2() const& noexcept { return static_cast<double>(::exp2(primitive_value)); } __attribute__((pure)) inline f64 exp_m1() const& noexcept { return static_cast<double>(::expm1(primitive_value)); } __attribute__((pure)) inline f64 floor() const& noexcept { return static_cast<double>(::floor(primitive_value)); } __attribute__((pure)) inline f64 hypot(f64 other) const& noexcept { return static_cast<double>( ::hypot(primitive_value, other.primitive_value)); } __attribute__((pure)) inline f64 ln() const& noexcept { return static_cast<double>(::log(primitive_value)); } __attribute__((pure)) inline f64 ln_1p() const& noexcept { return static_cast<double>(::log1p(primitive_value)); } __attribute__((pure)) inline f64 log10() const& noexcept { return static_cast<double>(::log10(primitive_value)); } __attribute__((pure)) inline f64 log2() const& noexcept { return static_cast<double>(::log2(primitive_value)); } __attribute__((pure)) inline f64 log(f64 base) const& noexcept { return ln() / base.ln(); } __attribute__((pure)) inline f64 max(f64 other) const& noexcept { return static_cast<double>( ::fmax(primitive_value, other.primitive_value)); } __attribute__((pure)) inline f64 min(f64 other) const& noexcept { return static_cast<double>( ::fmin(primitive_value, other.primitive_value)); } __attribute__((pure)) inline f64 mul_add(f64 a, f64 b) const& noexcept { return static_cast<double>( ::fma(primitive_value, a.primitive_value, b.primitive_value)); } __attribute__((pure)) inline f64 next_toward(f64 toward) const& noexcept { return __private::next_toward(primitive_value, toward.primitive_value); } __attribute__((pure)) inline f64 powf(f64 n) const& noexcept { return static_cast<double>(::pow(primitive_value, n.primitive_value)); } __attribute__((pure)) inline f64 powi(i32 n) const& noexcept { return static_cast<double>( ::pow(primitive_value, int{n.primitive_value})); } __attribute__((pure)) inline f64 recip() const& noexcept { return double{1} / primitive_value; } __attribute__((pure)) inline f64 round() const& noexcept { return __private::float_round(primitive_value); } __attribute__((pure)) inline f64 signum() const& noexcept { return __private::float_signum(primitive_value); } __attribute__((pure)) inline f64 sin() const& noexcept { return static_cast<double>(::sin(primitive_value)); } __attribute__((pure)) inline f64 sinh() const& noexcept { return static_cast<double>(::sinh(primitive_value)); } __attribute__((pure)) inline f64 sqrt() const& noexcept { if (primitive_value < -double{0}) [[unlikely]] return NAN; return static_cast<double>(::sqrt(primitive_value)); } __attribute__((pure)) inline f64 tan() const& noexcept { return static_cast<double>(::tan(primitive_value)); } __attribute__((pure)) inline f64 tanh() const& noexcept { return static_cast<double>(::tanh(primitive_value)); } __attribute__((pure)) inline f64 fract() const& noexcept { return primitive_value - __private::truncate_float(primitive_value); } __attribute__((pure)) inline f64 trunc() const& noexcept { return __private::truncate_float(primitive_value); } __attribute__((pure)) inline f64 to_degrees() const& noexcept { constexpr auto PIS_IN_180 = double{57.2957795130823208767981548141051703}; return primitive_value * PIS_IN_180; } __attribute__((pure)) inline f64 to_radians() const& noexcept { return primitive_value * (consts::PI.primitive_value / double{180}); } template <Integer I> __attribute__((pure)) constexpr inline I to_int_unchecked( ::sus::marker::UnsafeFnMarker) const& noexcept { return static_cast<decltype(I::primitive_value)>(primitive_value); } __attribute__((pure)) static f64 from_bits(u64 v) noexcept { return std::bit_cast<f64>(v); } __attribute__((pure)) constexpr inline u64 to_bits() const& noexcept { return std::bit_cast<decltype(u64::primitive_value)>(primitive_value); } __attribute__((pure)) constexpr inline FpCategory classify() const& noexcept { return __private::float_category(primitive_value); } __attribute__((pure)) constexpr inline bool is_finite() const& noexcept { return !__private::float_is_inf_or_nan(primitive_value); } __attribute__((pure)) constexpr inline bool is_infinite() const& noexcept { return __private::float_is_inf(primitive_value); } __attribute__((pure)) constexpr inline bool is_nan() const& noexcept { return __private::float_is_nan(primitive_value); } __attribute__((pure)) constexpr inline bool is_normal() const& noexcept { return __private::float_is_normal(primitive_value); } __attribute__((pure)) constexpr inline bool is_sign_negative() const& noexcept { return __private::float_signbit(primitive_value); } __attribute__((pure)) constexpr inline bool is_sign_positive() const& noexcept { return !__private::float_signbit(primitive_value); } __attribute__((pure)) constexpr inline bool is_subnormal() const& noexcept { return !__private::float_is_zero(primitive_value) && __private::float_nonzero_is_subnormal(primitive_value); } __attribute__((pure)) constexpr inline f64 clamp(f64 min, f64 max) const& noexcept { check(!min.is_nan() && !max.is_nan() && min.primitive_value <= max.primitive_value); return __private::float_clamp(::sus::marker::unsafe_fn, primitive_value, min.primitive_value, max.primitive_value); } __attribute__((pure)) f64 div_euclid(f64 rhs) const& noexcept { const auto q = (*this / rhs).trunc(); if (*this % rhs < double{0}) { if (rhs > f64{double{0}}) return q - f64{double{1}}; else return q + f64{double{1}}; } return q; } __attribute__((pure)) f64 rem_euclid(f64 rhs) const& noexcept { const auto r = *this % rhs; if (r < f64{double{0}}) return r + rhs.abs(); else return r; } __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<double>()> to_be_bytes() const& noexcept; __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<double>()> to_le_bytes() const& noexcept; __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<double>()> to_ne_bytes() const& noexcept; __attribute__((pure)) static f64 from_be_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<double>()>& bytes) noexcept; __attribute__((pure)) static f64 from_le_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<double>()>& bytes) noexcept; __attribute__((pure)) static f64 from_ne_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<double>()>& bytes) noexcept; }; inline constexpr double f64::MIN_PRIMITIVE = __private::min_value<double>(); inline constexpr double f64::MAX_PRIMITIVE = __private::max_value<double>(); inline constexpr f64 f64::MIN = f64(f64::MIN_PRIMITIVE); inline constexpr f64 f64::MAX = f64(f64::MAX_PRIMITIVE); inline constexpr u32 f64::RADIX = __private::radix<double>(); inline constexpr u32 f64::MANTISSA_DIGITS = __private::num_mantissa_digits<double>(); inline constexpr u32 f64::DIGITS = __private::num_digits<double>(); inline constexpr f64 f64::EPSILON = f64(__private::epsilon<double>()); inline constexpr f64 f64::MIN_POSITIVE = f64(__private::min_positive_value<double>()); inline constexpr i32 f64::MIN_EXP = __private::min_exp<double>(); inline constexpr i32 f64::MAX_EXP = __private::max_exp<double>(); inline constexpr i32 f64::MIN_10_EXP = __private::min_10_exp<double>(); inline constexpr i32 f64::MAX_10_EXP = __private::max_10_exp<double>(); inline constexpr f64 f64::NAN = f64(__private::nan<double>()); inline constexpr f64 f64::INFINITY = f64(__private::infinity<double>()); inline constexpr f64 f64::NEG_INFINITY = f64(__private::negative_infinity<double>()); inline constexpr f64 f64::consts::E = f64(2.7182818284590452353602874713526620); inline constexpr f64 f64::consts::FRAC_1_PI = f64(0.3183098861837906715377675267450280); inline constexpr f64 f64::consts::FRAC_1_SQRT_2 = f64(0.70710678118654760); inline constexpr f64 f64::consts::FRAC_2_PI = f64(0.63661977236758140); inline constexpr f64 f64::consts::FRAC_2_SQRT_PI = f64(1.12837916709551260); inline constexpr f64 f64::consts::FRAC_PI_2 = f64(1.57079632679489660); inline constexpr f64 f64::consts::FRAC_PI_3 = f64(1.04719755119659790); inline constexpr f64 f64::consts::FRAC_PI_4 = f64(0.78539816339744830); inline constexpr f64 f64::consts::FRAC_PI_6 = f64(0.52359877559829890); inline constexpr f64 f64::consts::FRAC_PI_8 = f64(0.392699081698724140); inline constexpr f64 f64::consts::LN_2 = f64(0.6931471805599453094172321214581760); inline constexpr f64 f64::consts::LN_10 = f64(2.3025850929940456840179914546843640); inline constexpr f64 f64::consts::LOG2_10 = f64(3.3219280948873620); inline constexpr f64 f64::consts::LOG2_E = f64(1.44269504088896340); inline constexpr f64 f64::consts::LOG10_2 = f64(0.30102999566398120); inline constexpr f64 f64::consts::LOG10_E = f64(0.43429448190325180); inline constexpr f64 f64::consts::PI = f64(3.1415926535897932384626433832795020); inline constexpr f64 f64::consts::SQRT_2 = f64(1.4142135623730950488016887242096980); inline constexpr f64 f64::consts::TAU = f64(6.2831853071795860); } ::sus::num::f32 inline consteval operator""_f32(long double val) { if (val > static_cast<long double>(::sus::num::f32::MAX_PRIMITIVE)) throw "Float literal out of bounds for ##T##"; return ::sus::num::f32(static_cast<decltype(::sus::num::f32::primitive_value)>(val)); } ::sus::num::f32 inline consteval operator""_f32(unsigned long long val) { return ::sus::num::f32(static_cast<decltype(::sus::num::f32::primitive_value)>(val)); }; ::sus::num::f64 inline consteval operator""_f64(long double val) { if (val > static_cast<long double>(::sus::num::f64::MAX_PRIMITIVE)) throw "Float literal out of bounds for ##T##"; return ::sus::num::f64(static_cast<decltype(::sus::num::f64::primitive_value)>(val)); } ::sus::num::f64 inline consteval operator""_f64(unsigned long long val) { return ::sus::num::f64(static_cast<decltype(::sus::num::f64::primitive_value)>(val)); }; namespace sus { using sus::num::f32; using sus::num::f64; } namespace sus::num { __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<float>()> f32::to_be_bytes() const& noexcept { return to_bits().to_be_bytes(); } __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<float>()> f32::to_le_bytes() const& noexcept { return to_bits().to_le_bytes(); } __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<float>()> f32::to_ne_bytes() const& noexcept { return to_bits().to_ne_bytes(); } __attribute__((pure)) inline f32 f32::from_be_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<float>()>& bytes) noexcept { return f32::from_bits(u32::from_be_bytes(bytes)); } __attribute__((pure)) inline f32 f32::from_le_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<float>()>& bytes) noexcept { return f32::from_bits(u32::from_le_bytes(bytes)); } __attribute__((pure)) inline f32 f32::from_ne_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<float>()>& bytes) noexcept { return f32::from_bits(u32::from_ne_bytes(bytes)); } } template <> struct std::hash<::sus::num::f32> { __attribute__((pure)) auto operator()(::sus::num::f32 u) const { return std::hash<float>()(u.primitive_value); } }; template <> struct std::equal_to<::sus::num::f32> { __attribute__((pure)) constexpr auto operator()(::sus::num::f32 l, ::sus::num::f32 r) const { return l == r; } }; namespace sus::num { __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<double>()> f64::to_be_bytes() const& noexcept { return to_bits().to_be_bytes(); } __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<double>()> f64::to_le_bytes() const& noexcept { return to_bits().to_le_bytes(); } __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<double>()> f64::to_ne_bytes() const& noexcept { return to_bits().to_ne_bytes(); } __attribute__((pure)) inline f64 f64::from_be_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<double>()>& bytes) noexcept { return f64::from_bits(u64::from_be_bytes(bytes)); } __attribute__((pure)) inline f64 f64::from_le_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<double>()>& bytes) noexcept { return f64::from_bits(u64::from_le_bytes(bytes)); } __attribute__((pure)) inline f64 f64::from_ne_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<double>()>& bytes) noexcept { return f64::from_bits(u64::from_ne_bytes(bytes)); } } template <> struct std::hash<::sus::num::f64> { __attribute__((pure)) auto operator()(::sus::num::f64 u) const { return std::hash<double>()(u.primitive_value); } }; template <> struct std::equal_to<::sus::num::f64> { __attribute__((pure)) constexpr auto operator()(::sus::num::f64 l, ::sus::num::f64 r) const { return l == r; } }; namespace sus::num { __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<int8_t>()> i8::to_be_bytes() const& noexcept { return to_be().to_ne_bytes(); } __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<int8_t>()> i8::to_le_bytes() const& noexcept { return to_le().to_ne_bytes(); } __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<int8_t>()> i8::to_ne_bytes() const& noexcept { auto bytes = ::sus::containers::Array<u8, ::sus::mem::size_of<int8_t>()>(); if (std::is_constant_evaluated()) { auto uval = __private::into_unsigned(primitive_value); for (auto i = size_t{0}; i < ::sus::mem::size_of<int8_t>(); ++i) { const auto last_byte = static_cast<uint8_t>(uval & 0xff); if (sus::assertions::is_little_endian()) bytes[i] = last_byte; else bytes[::sus::mem::size_of<int8_t>() - 1 - i] = last_byte; if constexpr (::sus::mem::size_of<int8_t>() > 1) uval >>= 8u; } return bytes; } else { ::sus::ptr::copy_nonoverlapping( ::sus::marker::unsafe_fn, reinterpret_cast<const char*>(&primitive_value), reinterpret_cast<char*>(bytes.as_mut_ptr()), ::sus::mem::size_of<int8_t>()); return bytes; } } __attribute__((pure)) inline constexpr i8 i8::from_be_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<int8_t>()>& bytes) noexcept { return from_be(from_ne_bytes(bytes)); } __attribute__((pure)) inline constexpr i8 i8::from_le_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<int8_t>()>& bytes) noexcept { return from_le(from_ne_bytes(bytes)); } __attribute__((pure)) inline constexpr i8 i8::from_ne_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<int8_t>()>& bytes) noexcept { using Unsigned = decltype(__private::into_unsigned(primitive_value)); Unsigned val; if (std::is_constant_evaluated()) { val = Unsigned{0}; for (auto i = size_t{0}; i < ::sus::mem::size_of<int8_t>(); ++i) { val |= bytes[i].primitive_value << (::sus::mem::size_of<int8_t>() - size_t{1} - i); } } else { ::sus::ptr::copy_nonoverlapping( ::sus::marker::unsafe_fn, reinterpret_cast<const char*>(bytes.as_ptr()), reinterpret_cast<char*>(&val), ::sus::mem::size_of<int8_t>()); } return __private::into_signed(val); } } template <> struct std::hash<::sus::num::i8> { __attribute__((pure)) auto operator()(::sus::num::i8 u) const noexcept { return std::hash<int8_t>()(u.primitive_value); } }; template <> struct std::equal_to<::sus::num::i8> { __attribute__((pure)) constexpr auto operator()(::sus::num::i8 l, ::sus::num::i8 r) const noexcept { return l == r; } }; namespace sus::num { __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<int16_t>()> i16::to_be_bytes() const& noexcept { return to_be().to_ne_bytes(); } __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<int16_t>()> i16::to_le_bytes() const& noexcept { return to_le().to_ne_bytes(); } __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<int16_t>()> i16::to_ne_bytes() const& noexcept { auto bytes = ::sus::containers::Array<u8, ::sus::mem::size_of<int16_t>()>(); if (std::is_constant_evaluated()) { auto uval = __private::into_unsigned(primitive_value); for (auto i = size_t{0}; i < ::sus::mem::size_of<int16_t>(); ++i) { const auto last_byte = static_cast<uint8_t>(uval & 0xff); if (sus::assertions::is_little_endian()) bytes[i] = last_byte; else bytes[::sus::mem::size_of<int16_t>() - 1 - i] = last_byte; if constexpr (::sus::mem::size_of<int16_t>() > 1) uval >>= 8u; } return bytes; } else { ::sus::ptr::copy_nonoverlapping( ::sus::marker::unsafe_fn, reinterpret_cast<const char*>(&primitive_value), reinterpret_cast<char*>(bytes.as_mut_ptr()), ::sus::mem::size_of<int16_t>()); return bytes; } } __attribute__((pure)) inline constexpr i16 i16::from_be_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<int16_t>()>& bytes) noexcept { return from_be(from_ne_bytes(bytes)); } __attribute__((pure)) inline constexpr i16 i16::from_le_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<int16_t>()>& bytes) noexcept { return from_le(from_ne_bytes(bytes)); } __attribute__((pure)) inline constexpr i16 i16::from_ne_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<int16_t>()>& bytes) noexcept { using Unsigned = decltype(__private::into_unsigned(primitive_value)); Unsigned val; if (std::is_constant_evaluated()) { val = Unsigned{0}; for (auto i = size_t{0}; i < ::sus::mem::size_of<int16_t>(); ++i) { val |= bytes[i].primitive_value << (::sus::mem::size_of<int16_t>() - size_t{1} - i); } } else { ::sus::ptr::copy_nonoverlapping( ::sus::marker::unsafe_fn, reinterpret_cast<const char*>(bytes.as_ptr()), reinterpret_cast<char*>(&val), ::sus::mem::size_of<int16_t>()); } return __private::into_signed(val); } } template <> struct std::hash<::sus::num::i16> { __attribute__((pure)) auto operator()(::sus::num::i16 u) const noexcept { return std::hash<int16_t>()(u.primitive_value); } }; template <> struct std::equal_to<::sus::num::i16> { __attribute__((pure)) constexpr auto operator()(::sus::num::i16 l, ::sus::num::i16 r) const noexcept { return l == r; } }; namespace sus::num { __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<int32_t>()> i32::to_be_bytes() const& noexcept { return to_be().to_ne_bytes(); } __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<int32_t>()> i32::to_le_bytes() const& noexcept { return to_le().to_ne_bytes(); } __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<int32_t>()> i32::to_ne_bytes() const& noexcept { auto bytes = ::sus::containers::Array<u8, ::sus::mem::size_of<int32_t>()>(); if (std::is_constant_evaluated()) { auto uval = __private::into_unsigned(primitive_value); for (auto i = size_t{0}; i < ::sus::mem::size_of<int32_t>(); ++i) { const auto last_byte = static_cast<uint8_t>(uval & 0xff); if (sus::assertions::is_little_endian()) bytes[i] = last_byte; else bytes[::sus::mem::size_of<int32_t>() - 1 - i] = last_byte; if constexpr (::sus::mem::size_of<int32_t>() > 1) uval >>= 8u; } return bytes; } else { ::sus::ptr::copy_nonoverlapping( ::sus::marker::unsafe_fn, reinterpret_cast<const char*>(&primitive_value), reinterpret_cast<char*>(bytes.as_mut_ptr()), ::sus::mem::size_of<int32_t>()); return bytes; } } __attribute__((pure)) inline constexpr i32 i32::from_be_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<int32_t>()>& bytes) noexcept { return from_be(from_ne_bytes(bytes)); } __attribute__((pure)) inline constexpr i32 i32::from_le_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<int32_t>()>& bytes) noexcept { return from_le(from_ne_bytes(bytes)); } __attribute__((pure)) inline constexpr i32 i32::from_ne_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<int32_t>()>& bytes) noexcept { using Unsigned = decltype(__private::into_unsigned(primitive_value)); Unsigned val; if (std::is_constant_evaluated()) { val = Unsigned{0}; for (auto i = size_t{0}; i < ::sus::mem::size_of<int32_t>(); ++i) { val |= bytes[i].primitive_value << (::sus::mem::size_of<int32_t>() - size_t{1} - i); } } else { ::sus::ptr::copy_nonoverlapping( ::sus::marker::unsafe_fn, reinterpret_cast<const char*>(bytes.as_ptr()), reinterpret_cast<char*>(&val), ::sus::mem::size_of<int32_t>()); } return __private::into_signed(val); } } template <> struct std::hash<::sus::num::i32> { __attribute__((pure)) auto operator()(::sus::num::i32 u) const noexcept { return std::hash<int32_t>()(u.primitive_value); } }; template <> struct std::equal_to<::sus::num::i32> { __attribute__((pure)) constexpr auto operator()(::sus::num::i32 l, ::sus::num::i32 r) const noexcept { return l == r; } }; namespace sus::num { __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<int64_t>()> i64::to_be_bytes() const& noexcept { return to_be().to_ne_bytes(); } __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<int64_t>()> i64::to_le_bytes() const& noexcept { return to_le().to_ne_bytes(); } __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of<int64_t>()> i64::to_ne_bytes() const& noexcept { auto bytes = ::sus::containers::Array<u8, ::sus::mem::size_of<int64_t>()>(); if (std::is_constant_evaluated()) { auto uval = __private::into_unsigned(primitive_value); for (auto i = size_t{0}; i < ::sus::mem::size_of<int64_t>(); ++i) { const auto last_byte = static_cast<uint8_t>(uval & 0xff); if (sus::assertions::is_little_endian()) bytes[i] = last_byte; else bytes[::sus::mem::size_of<int64_t>() - 1 - i] = last_byte; if constexpr (::sus::mem::size_of<int64_t>() > 1) uval >>= 8u; } return bytes; } else { ::sus::ptr::copy_nonoverlapping( ::sus::marker::unsafe_fn, reinterpret_cast<const char*>(&primitive_value), reinterpret_cast<char*>(bytes.as_mut_ptr()), ::sus::mem::size_of<int64_t>()); return bytes; } } __attribute__((pure)) inline constexpr i64 i64::from_be_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<int64_t>()>& bytes) noexcept { return from_be(from_ne_bytes(bytes)); } __attribute__((pure)) inline constexpr i64 i64::from_le_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<int64_t>()>& bytes) noexcept { return from_le(from_ne_bytes(bytes)); } __attribute__((pure)) inline constexpr i64 i64::from_ne_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of<int64_t>()>& bytes) noexcept { using Unsigned = decltype(__private::into_unsigned(primitive_value)); Unsigned val; if (std::is_constant_evaluated()) { val = Unsigned{0}; for (auto i = size_t{0}; i < ::sus::mem::size_of<int64_t>(); ++i) { val |= bytes[i].primitive_value << (::sus::mem::size_of<int64_t>() - size_t{1} - i); } } else { ::sus::ptr::copy_nonoverlapping( ::sus::marker::unsafe_fn, reinterpret_cast<const char*>(bytes.as_ptr()), reinterpret_cast<char*>(&val), ::sus::mem::size_of<int64_t>()); } return __private::into_signed(val); } } template <> struct std::hash<::sus::num::i64> { __attribute__((pure)) auto operator()(::sus::num::i64 u) const noexcept { return std::hash<int64_t>()(u.primitive_value); } }; template <> struct std::equal_to<::sus::num::i64> { __attribute__((pure)) constexpr auto operator()(::sus::num::i64 l, ::sus::num::i64 r) const noexcept { return l == r; } }; namespace sus::num { __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of< ::sus::num::__private::addr_type<>::signed_type>()> isize::to_be_bytes() const& noexcept { return to_be().to_ne_bytes(); } __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of< ::sus::num::__private::addr_type<>::signed_type>()> isize::to_le_bytes() const& noexcept { return to_le().to_ne_bytes(); } __attribute__((pure)) constexpr ::sus::containers::Array<u8, ::sus::mem::size_of< ::sus::num::__private::addr_type<>::signed_type>()> isize::to_ne_bytes() const& noexcept { auto bytes = ::sus::containers::Array<u8, ::sus::mem::size_of< ::sus::num::__private::addr_type<>::signed_type>()>(); if (std::is_constant_evaluated()) { auto uval = __private::into_unsigned(primitive_value); for (auto i = size_t{0}; i < ::sus::mem::size_of< ::sus::num::__private::addr_type<>::signed_type>(); ++i) { const auto last_byte = static_cast<uint8_t>(uval & 0xff); if (sus::assertions::is_little_endian()) bytes[i] = last_byte; else bytes[::sus::mem::size_of< ::sus::num::__private::addr_type<>::signed_type>() - 1 - i] = last_byte; if constexpr (::sus::mem::size_of< ::sus::num::__private::addr_type<>::signed_type>() > 1) uval >>= 8u; } return bytes; } else { ::sus::ptr::copy_nonoverlapping( ::sus::marker::unsafe_fn, reinterpret_cast<const char*>(&primitive_value), reinterpret_cast<char*>(bytes.as_mut_ptr()), ::sus::mem::size_of< ::sus::num::__private::addr_type<>::signed_type>()); return bytes; } } __attribute__((pure)) inline constexpr isize isize::from_be_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of< ::sus::num::__private::addr_type<>::signed_type>()>& bytes) noexcept { return from_be(from_ne_bytes(bytes)); } __attribute__((pure)) inline constexpr isize isize::from_le_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of< ::sus::num::__private::addr_type<>::signed_type>()>& bytes) noexcept { return from_le(from_ne_bytes(bytes)); } __attribute__((pure)) inline constexpr isize isize::from_ne_bytes( const ::sus::containers::Array<u8, ::sus::mem::size_of< ::sus::num::__private::addr_type<>::signed_type>()>& bytes) noexcept { using Unsigned = decltype(__private::into_unsigned(primitive_value)); Unsigned val; if (std::is_constant_evaluated()) { val = Unsigned{0}; for (auto i = size_t{0}; i < ::sus::mem::size_of< ::sus::num::__private::addr_type<>::signed_type>(); ++i) { val |= bytes[i].primitive_value << (::sus::mem::size_of< ::sus::num::__private::addr_type<>::signed_type>() - size_t{1} - i); } } else { ::sus::ptr::copy_nonoverlapping( ::sus::marker::unsafe_fn, reinterpret_cast<const char*>(bytes.as_ptr()), reinterpret_cast<char*>(&val), ::sus::mem::size_of< ::sus::num::__private::addr_type<>::signed_type>()); } return __private::into_signed(val); } } template <> struct std::hash<::sus::num::isize> { __attribute__((pure)) auto operator()(::sus::num::isize u) const noexcept { return std::hash< ::sus::num::__private::addr_type<>::signed_type>()(u.primitive_value); } }; template <> struct std::equal_to<::sus::num::isize> { __attribute__((pure)) constexpr auto operator()(::sus::num::isize l, ::sus::num::isize r) const noexcept { return l == r; } }; namespace sus::ops { namespace __private { template <bool IsSigned> struct RangeLiteralDeducer { using Int = std::conditional_t<IsSigned, ::sus::num::isize, ::sus::num::usize>; using Digit = std::conditional_t<IsSigned, int, unsigned int>; static void invalid(const char*); constexpr RangeLiteralDeducer(const char* c) { size_t i = 0u; bool has_lower = false; bool negate_lower = false; if (c[i] != '.') { if constexpr (IsSigned) { if (c[i] == '-') { negate_lower = true; i += 1u; } } if (c[i] < '0' || c[i] > '9') invalid("Invalid lower bound number in range literal"); { auto digit = static_cast<Digit>(c[i] - '0'); if constexpr (IsSigned) { if (negate_lower) digit = -digit; } lower = digit; } i += 1u; for (; c[i] != '\0' && c[i] != '.'; i += 1u) { if (c[i] != '\'') { if (c[i] < '0' || c[i] > '9') invalid("Invalid lower bound number in range literal"); auto mul = lower.checked_mul(Digit{10}); if (mul.is_none()) invalid("Lower bound is out of range"); lower = ::sus::move(mul).unwrap(); { auto digit = static_cast<Digit>(c[i] - '0'); if constexpr (IsSigned) { if (negate_lower) digit = -digit; } auto add = lower.checked_add(digit); if (add.is_none()) invalid("Lower bound is out of range"); lower = ::sus::move(add).unwrap(); } } else if (c[i + 1] < '0' || c[i + 1] > '9') { invalid("Invalid lower bound number in range literal"); } } has_lower = true; } if (c[i] != '.' || c[i + 1u] != '.') invalid("Missing `..` in range literal"); i += 2u; if (c[i] == '\0') { if (has_lower) { type = LowerBound; upper = 0u; return; } else { type = NoBound; lower = 0u; upper = 0u; return; } } bool include_upper = false; if (c[i] == '=') { include_upper = true; i += 1u; } bool negate_upper = false; if constexpr (IsSigned) { if (c[i] == '-') { negate_upper = true; i += 1u; } } if (c[i] < '0' || c[i] > '9') invalid("Invalid upper bound number in range literal"); { auto digit = static_cast<Digit>(c[i] - '0'); if constexpr (IsSigned) { if (negate_upper) digit = -digit; } upper = digit; } i += 1u; for (; c[i] != '\0'; i += 1u) { if (c[i] != '\'') { if (c[i] < '0' || c[i] > '9') invalid("Invalid upper bound number in range literal"); auto mul = upper.checked_mul(Digit{10}); if (mul.is_none()) invalid("Upper bound is out of range"); upper = ::sus::move(mul).unwrap(); { auto digit = static_cast<Digit>(c[i] - '0'); if constexpr (IsSigned) { if (negate_upper) digit = -digit; } auto add = upper.checked_add(digit); if (add.is_none()) invalid("Upper bound is out of range"); upper = ::sus::move(add).unwrap(); } } else if (c[i + 1] < '0' || c[i + 1] > '9') { invalid("Invalid upper bound number in range literal"); } } if (include_upper) upper += 1u; if (has_lower) { type = LowerAndUpperBound; return; } else { type = UpperBound; lower = 0u; } } enum { NoBound, LowerBound, UpperBound, LowerAndUpperBound, } type; Int lower; Int upper; }; } } template <::sus::ops::__private::RangeLiteralDeducer<false> D> constexpr auto operator""_r() { using ::sus::ops::__private::RangeLiteralDeducer; if constexpr (D.type == RangeLiteralDeducer<false>::NoBound) return ::sus::ops::RangeFull<::sus::num::usize>(); else if constexpr (D.type == RangeLiteralDeducer<false>::LowerBound) return ::sus::ops::RangeFrom<::sus::num::usize>(D.lower); else if constexpr (D.type == RangeLiteralDeducer<false>::UpperBound) return ::sus::ops::RangeTo<::sus::num::usize>(D.upper); else return ::sus::ops::Range<::sus::num::usize>(D.lower, D.upper); } template <::sus::ops::__private::RangeLiteralDeducer<true> D> constexpr auto operator""_rs() { using ::sus::ops::__private::RangeLiteralDeducer; if constexpr (D.type == RangeLiteralDeducer<true>::NoBound) return ::sus::ops::RangeFull<::sus::num::isize>(); else if constexpr (D.type == RangeLiteralDeducer<true>::LowerBound) return ::sus::ops::RangeFrom<::sus::num::isize>(D.lower); else if constexpr (D.type == RangeLiteralDeducer<true>::UpperBound) return ::sus::ops::RangeTo<::sus::num::isize>(D.upper); else return ::sus::ops::Range<::sus::num::isize>(D.lower, D.upper); } using sus::containers::Vec; using sus::marker::unsafe_fn; using sus::num::f32; using sus::num::f64; using sus::num::i16; using sus::num::i32; using sus::num::i64; using sus::num::i8; using sus::num::isize; using sus::num::u16; using sus::num::u32; using sus::num::u64; using sus::num::u8; using sus::num::usize; using sus::num::uptr; int main() { static_assert(sus::Vec<Vec<i32>>::with(sus::Vec<i32>::with(1, 2, 3), // sus::Vec<i32>::with(4), // sus::Vec<i32>::with(), // sus::Vec<i32>::with(5, 6)) .into_iter() .flatten() .sum() == 1 + 2 + 3 + 4 + 5 + 6); }
Become a Patron
Sponsor on GitHub
Donate via PayPal
Source on GitHub
Mailing list
Installed libraries
Wiki
Report an issue
How it works
Contact the author
CE on Mastodon
About the author
Statistics
Changelog
Version tree